---
modificationDate: May 11, 2026
title: Using Clerk
description: Learn how to add Clerk authentication and user management in your Expo and React Native projects.
platforms: ['android', 'ios', 'web']
---

<AgentInstructions>

## Submitting Feedback

If this page contains errors, outdated information, or gaps that blocked you from completing a task, report it so the docs can be improved:

curl -X POST https://api.expo.dev/v2/feedback/docs-send -H 'Content-Type: application/json' -d '{"url":"/guides/using-clerk/","feedback":"🤖 Agent feedback: <specific, actionable description>"}'

Only submit when you have something specific and actionable to report.

</AgentInstructions>

# Using Clerk

Learn how to add Clerk authentication and user management in your Expo and React Native projects.
Android, iOS, Web

> For the complete documentation index, see [llms.txt](/llms.txt). Use this file to discover all available pages.

[Clerk](https://clerk.com/expo-authentication) is an authentication and user management platform that provides sign-up, sign-in, multi-factor authentication, social sign-in, organizations, and a hosted user database. The [`@clerk/expo`](https://www.npmjs.com/package/@clerk/expo) SDK gives you React hooks, control components, and prebuilt native UI components that render with Jetpack Compose on Android and SwiftUI on iOS.

This guide shows you how to install `@clerk/expo`, wrap your app in `<ClerkProvider>`, and choose the integration approach that fits your project. It targets `@clerk/expo` Core 3 (the 3.x release line), which supports Expo SDK 53, 54, and 55.

## Choose your integration approach

`@clerk/expo` supports three approaches. Pick the one that matches your needs — you can change later without rewriting your app.

| Approach | What you build | Runs in Expo Go | Best for |
| --- | --- | --- | --- |
| JavaScript only | Your own React Native screens that call `useSignIn()` and `useSignUp()` | ✓ | Maximum UI control, prototyping in Expo Go |
| JavaScript with native sign-in | Your own screens plus native Sign in with Google and Sign in with Apple buttons | ✗ | Apps that want a custom look but native social sign-in |
| Native UI components | Drop in `<AuthView />`, `<UserButton />`, and `<UserProfileView />` from `@clerk/expo/native` | ✗ | The fastest path to a complete sign-in and account management UI |

> The native UI components in `@clerk/expo/native` are currently in beta. They render with Jetpack Compose on Android and SwiftUI on iOS and they synchronize the signed-in session back to the JavaScript SDK so all `@clerk/expo` hooks (such as `useAuth()` and `useUser()`) stay in sync.

## Prerequisites

Prerequisites

4 requirements

1.

Create a Clerk account and application

Sign up at the [Clerk Dashboard](https://dashboard.clerk.com/) and create an application.

2.

Enable the Native API

Open the [Native applications](https://dashboard.clerk.com/last-active?path=native-applications) page in the Clerk Dashboard and ensure **Native API** is on. This is required for any Expo integration that uses `@clerk/expo`.

3.

Use Expo SDK 53 or later

`@clerk/expo` Core 3 has a peer dependency of `expo: >=53 <56`.

4.

Use a development build for native features

The native sign-in and native UI component approaches require a development build. The JavaScript-only approach also works in Expo Go.

## Install and configure Clerk

### Install `@clerk/expo` and `expo-secure-store`

Use `npx expo install` so versions match your Expo SDK:

```sh
npx expo install @clerk/expo expo-secure-store
```

`expo-secure-store` is a peer dependency. Clerk uses it through `@clerk/expo/token-cache` to encrypt session tokens with the iOS Keychain and the Android Keystore.

If you plan to use native Sign in with Google, also install `expo-crypto`:

```sh
npx expo install expo-crypto
```

For native Sign in with Apple, install both `expo-apple-authentication` and `expo-crypto`:

```sh
npx expo install expo-apple-authentication expo-crypto
```

You do not need any of these extra packages if you only use `<AuthView />` from `@clerk/expo/native`, since the component handles social sign-in flows internally.

### Add the Clerk config plugin

Add `@clerk/expo` to the `plugins` array in your [app config](/workflow/configuration):

```json
{
  "expo": {
    "plugins": ["@clerk/expo"]
  }
}
```

The plugin configures the iOS URL scheme for native Sign in with Google (when `EXPO_PUBLIC_CLERK_GOOGLE_IOS_URL_SCHEME` is set) and applies the Android packaging fixes required by the underlying `clerk-android` SDK. The Apple Sign In entitlement is added by the plugin from `expo-apple-authentication` library, if you install it.

### Add your Clerk Publishable Key

Copy your Publishable Key from the [API keys](https://dashboard.clerk.com/last-active?path=api-keys) page in the Clerk Dashboard, then add it to a **.env** file in the root of your project:

```text
EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_your-key-here
```

The `EXPO_PUBLIC_` prefix is required because [Expo inlines these values at build time](/guides/environment-variables#reading-environment-variables-from-env-files) so they are available in your JavaScript bundle. Clerk's Publishable Key is safe to expose. **Do not** put Secret Keys behind the `EXPO_PUBLIC_` prefix.

### Wrap your app in `<ClerkProvider>`

In your root layout file (**src/app/_layout.tsx** with Expo Router), wrap your app in `<ClerkProvider>` and pass the Publishable Key. Passing `tokenCache` explicitly is recommended:

```tsx
import { ClerkProvider } from '@clerk/expo';
import { tokenCache } from '@clerk/expo/token-cache';
import { Slot } from 'expo-router';

const publishableKey = process.env.EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY!;

if (!publishableKey) {
  throw new Error('Add your Clerk Publishable Key to the .env file');
}

export default function RootLayout() {
  return (
    <ClerkProvider publishableKey={publishableKey} tokenCache={tokenCache}>
      <Slot />
    </ClerkProvider>
  );
}
```

In Core 3, `publishableKey` is required on `<ClerkProvider>` for Expo apps. Environment variables inside **node_modules** are not inlined during production React Native builds, so the prop must be passed explicitly.

`tokenCache` from `@clerk/expo/token-cache` persists the user's session across app restarts using `expo-secure-store`. Passing it explicitly makes the dependency clear and lets you swap in a custom cache implementation later.

## Build your sign-in screen

The next step depends on which approach you chose. The tabs below show the minimum code for each.

Drop `<AuthView />` into a screen. It renders a complete native sign-in and sign-up interface that handles email, phone, passkeys, multi-factor authentication, and any social connection enabled in the Clerk Dashboard:

```tsx
import { AuthView } from '@clerk/expo/native';
import { useAuth } from '@clerk/expo';
import { useRouter } from 'expo-router';
import { useEffect } from 'react';

export default function SignInScreen() {
  const { isSignedIn } = useAuth({ treatPendingAsSignedOut: false });
  const router = useRouter();

  useEffect(() => {
    if (isSignedIn) {
      router.replace('/(home)');
    }
  }, [isSignedIn]);

  return <AuthView mode="signInOrUp" />;
}
```

After the user signs in, the native session is synchronized back to the JavaScript SDK, so `useAuth()` and `useUser()` reflect the signed-in state. Pass `treatPendingAsSignedOut: false` to `useAuth()` so the brief native-to-JS session sync isn't reported as a signed-out state, which can otherwise cause redirect loops on screens that key navigation off `isSignedIn`.

`<AuthView />` accepts `mode="signIn" | "signUp" | "signInOrUp"` and an optional `isDismissable` boolean.

To show the user's avatar and a profile modal elsewhere in your app, use `<UserButton />`:

```tsx
import { UserButton } from '@clerk/expo/native';
import { Show } from '@clerk/expo';
import { View } from 'react-native';

export function Header() {
  return (
    <Show when="signed-in">
      <View style={{ width: 36, height: 36, borderRadius: 18, overflow: 'hidden' }}>
        <UserButton />
      </View>
    </Show>
  );
}
```

`<UserButton />` fills its parent, so the parent controls size and shape. To open the native profile modal from any other UI, use the `useUserProfileModal()` hook:

```tsx
import { useUserProfileModal } from '@clerk/expo';
import { Pressable, Text } from 'react-native';

export function ProfileLink() {
  const { presentUserProfile, isAvailable } = useUserProfileModal();
  return (
    <Pressable onPress={presentUserProfile} disabled={!isAvailable}>
      <Text>Manage profile</Text>
    </Pressable>
  );
}
```

This approach requires a development build because the components are backed by native modules:

```sh
npx expo run:android
npx expo run:ios
eas build --platform ios --profile development
```

## Read the signed-in user

Anywhere in your app, use `useUser()` and `useAuth()` to read user data, plus `<Show>` and `useClerk()` to protect content and sign out:

```tsx
import { Show, useClerk, useUser } from '@clerk/expo';
import { Link } from 'expo-router';
import { Pressable, Text, View } from 'react-native';

export default function HomeScreen() {
  const { user } = useUser();
  const { signOut } = useClerk();

  return (
    <View>
      <Show when="signed-in">
        <Text>Hello, {user?.firstName ?? 'friend'}</Text>
        <Pressable onPress={() => signOut()}>
          <Text>Sign out</Text>
        </Pressable>
      </Show>
      <Show when="signed-out">
        <Link href="/(auth)/sign-in">
          <Text>Sign in</Text>
        </Link>
      </Show>
    </View>
  );
}
```

`<Show>` replaces the legacy `<SignedIn>`, `<SignedOut>`, and `<Protect>` components from earlier versions of the SDK. It also accepts `when={{ role: '...' }}`, `when={{ permission: '...' }}`, and other authorization predicates.

## Run the app

```sh
npx expo run:android
```

## Next steps

[Clerk Expo quickstart](https://clerk.com/docs/expo/getting-started/quickstart) — Step-by-step instructions for setting up each of the three integration approaches, with companion repositories on GitHub.

[Native components reference](https://clerk.com/docs/reference/expo/native-components/overview) — API reference for AuthView, UserButton, and UserProfileView, including configuration, theming, and platform requirements.

[Sign in with Google](https://clerk.com/docs/expo/guides/configure/auth-strategies/sign-in-with-google) — Set up native Sign in with Google for Android and iOS using ASAuthorization and Credential Manager.

[Sign in with Apple](https://clerk.com/docs/expo/guides/configure/auth-strategies/sign-in-with-apple) — Set up native Sign in with Apple to satisfy App Store Guideline 4.8.

[Protect content and read user data](https://clerk.com/docs/expo/guides/users/reading) — Use Clerk's hooks and Show component to protect routes and access user data in your Expo app.

[Deploy an Expo app to production with Clerk](https://clerk.com/docs/guides/development/deployment/expo) — Configure production credentials, allowlist mobile SSO redirects, and ship with EAS Build.
