This guide targets Expo SDK 55 (React Native 0.83, React 19.2). SDK 55 requires the New Architecture — the Legacy Architecture is no longer supported. If you are upgrading from an older SDK, see the Expo SDK 55 upgrade guide.
Installation
Configure a Better Auth backend
Before using Better Auth with Expo, you need a Better Auth backend. You can use a separate server or host your Better Auth instance inside the Expo app using Expo API Routes.To use Expo API Routes, create a catch-all API route and export the handler for both methods:For a standalone server setup, follow the installation guide.
app/api/auth/[...auth]+api.ts
Install server dependencies
Install Better Auth and the Expo server plugin into your server (or Expo) project:
Install client dependencies
Install Better Auth and the Expo client plugin into your Expo application:If you plan to use social providers (Google, Apple, etc.), you also need:
Add the Expo plugin on your server
Add the
expo server plugin to your Better Auth instance:lib/auth.ts
Initialise the Better Auth client
Create the auth client with The
createAuthClient from better-auth/react and add the expoClient plugin. The plugin handles secure cookie storage via expo-secure-store and manages OAuth browser sessions.lib/auth-client.ts
Include the full URL with path if you changed the default
/api/auth base path.expoClient plugin:- Enables social auth flows by handling OAuth URLs and callbacks in the Expo web browser.
- Stores session cookies securely in
expo-secure-storeand appends them to auth request headers automatically.
Configure scheme and trusted origins
Better Auth uses deep links to redirect users back to your app after OAuth. Add your app scheme to Then add it to your Better Auth config:For development, Expo uses the
trustedOrigins in your auth config.First, define the scheme in app.json:app.json
lib/auth.ts
exp:// scheme with your device’s local IP. You can conditionally allow it:lib/auth.ts
Configure Metro bundler
Better Auth relies on Clear the Metro cache after any config change:
package.json exports for module resolution. From Expo SDK 53+, package exports are enabled in Metro by default — no extra configuration is needed.If you have a custom metro.config.js, ensure you are not disabling package exports:metro.config.js
Usage
Sign-in and sign-up
- Sign in
- Sign up
app/sign-in.tsx
Social sign-in
Pass a relative callback path tosignIn.social. On native, the Expo plugin automatically converts it to a deep link using Linking.createURL.
app/social-sign-in.tsx
On native (iOS/Android),
signIn.social does not navigate automatically. Handle navigation yourself after the call resolves. Browser behaviour differs by platform — see the Expo WebBrowser docs.IdToken sign-in
If you obtain an ID token from a native provider SDK, you can verify it server-side withsignIn.social and the idToken option:
app/social-sign-in.tsx
Session
Use theuseSession hook to access the current user’s session reactively. On native, the session is cached in SecureStore to avoid a loading spinner on app restart.
app/index.tsx
Making authenticated requests
To send authenticated requests from native, retrieve the session cookie fromSecureStore and attach it manually to your request headers.
Client options
storage
The storage mechanism used to persist session data and cookies. Defaults toexpo-secure-store.
lib/auth-client.ts
scheme
The deep link scheme used to redirect back to your app after OAuth. By default, Better Auth reads this fromapp.json. Override it when necessary.
disableCache
Set totrue to prevent session data from being cached in SecureStore.
cookiePrefix
Prefix (or array of prefixes) used to identify Better Auth cookies. Prevents infinite refetching when third-party cookies are present. Defaults to"better-auth".
If you use plugins with custom cookie names (e.g.
webAuthnChallengeCookie), include the corresponding prefix in the cookiePrefix array. See the Passkey plugin docs for details.