Crossmint Auth on React Native is headless — there is no pre-built login modal.
You build your own UI and call the SDK hooks directly. This guide walks through both
email OTP and OAuth login flows.
Before you start
Set up your project and get an API key.
Expo Wallets Quickstart
See a full working example with auth and wallets.
Install the SDK
Install the Crossmint React Native SDK and its required Expo peer dependencies:The SDK requires the following Expo packages:
| Package | Purpose |
|---|---|
expo-secure-store | Encrypted token storage (Keychain on iOS, Keystore on Android) |
expo-web-browser | Opens the OAuth consent screen in a system browser |
expo-device | Detects device capabilities for secure storage availability |
expo-linking | Listens for OAuth deep-link redirects back to your app |
Configure your app scheme
OAuth redirects require a deep link scheme so the browser can return to your app after login.Add a
scheme to your app.json (or app.config.ts):app.json
Add the Crossmint providers to your app
Wrap your application with
CrossmintProvider and CrossmintAuthProvider.providers.tsx
CrossmintAuthProvider Props
CrossmintAuthProvider Props
| Prop | Type | Description |
|---|---|---|
appSchema | string | string[] | Override the deep link scheme. Defaults to the scheme in your Expo config. |
storageProvider | StorageProvider | Custom token storage implementation. Defaults to expo-secure-store. |
onLoginSuccess | (user) => void | Callback fired after a successful login. |
Build the login screen
Use the
useCrossmintAuth hook to access auth functions. Unlike the React web SDK, there is no
pre-built modal — you call loginWithOAuth and crossmintAuth.sendEmailOtp / crossmintAuth.confirmEmailOtp directly.Email OTP Login
LoginScreen.tsx
OAuth Login (Google, Twitter)
OAuthButton.tsx
How OAuth Works on Android vs iOS
How OAuth Works on Android vs iOS
The SDK handles platform differences automatically:
- iOS: Uses
WebBrowser.openAuthSessionAsync, which opens an in-app authentication session (ASWebAuthenticationSession). The redirect URL is intercepted by the authentication session before it reaches your app’s URL routing, soLinking.useURL()remainsnullafter the OAuth flow. There is no double invocation —createAuthSessionis called only once by the SDK internally. - Android: Uses
WebBrowser.openBrowserAsync, which opens the system browser. The OAuth provider redirects back to your app via the deep link scheme. You must listen for the incoming URL withLinking.useURL()and pass it tocreateAuthSessionyourself, as shown in the example above.
Linking.useURL() + createAuthSession pattern works on both platforms, so a single
code path is sufficient.Auth Status Values
Thestatus field returned by useCrossmintAuth can be one of the following:
| Status | Description |
|---|---|
"initializing" | The SDK is loading stored tokens and checking session validity |
"logged-out" | No active session. Show your login screen |
"in-progress" | An OAuth or OTP flow is currently in progress |
"logged-in" | The user is authenticated. user and jwt are available |
Token Storage
By default, the SDK stores authentication tokens usingexpo-secure-store, which encrypts data
at rest using the platform keychain (iOS) or keystore (Android). This means tokens persist
across app restarts and are protected by the device’s hardware-backed security.
You can provide a custom storage implementation via the storageProvider prop on
CrossmintAuthProvider if you need a different storage backend.
Differences from the React Web SDK
| Feature | React (Web) | React Native |
|---|---|---|
| Login UI | Pre-built modal via login() | Headless — build your own UI |
| Auth hook | useAuth() | useCrossmintAuth() |
| OAuth flow | Popup / redirect in browser | System browser via expo-web-browser |
| OAuth callback | Handled automatically | Listen with Linking.useURL() + createAuthSession() |
| Token storage | Browser localStorage / cookies | expo-secure-store (encrypted) |
| Package | @crossmint/client-sdk-react-ui | @crossmint/client-sdk-react-native-ui |
| Deep link scheme | Not required | Required in app.json for OAuth |
| Email OTP | Handled by modal | Call sendEmailOtp / confirmEmailOtp manually |
Moving to Production
When you are ready to go to production, Crossmint recommends:- Set up your own auth provider (Auth0, Firebase, Supabase, Stytch, etc.) and follow the Bring Your Own Auth guide to integrate it with Crossmint via JWT.
- Create a developer account on the production console.
- Create a production client API key on the API Keys page with the API scopes
users.create,users.read,wallets.read. - Configure JWT authentication for your auth provider in the Crossmint Console.
Next Steps
- Create Smart Wallets on sign up using the wallets React Native quickstart
- Bring Your Own Auth, recommended for production
- Read and update user information
- Use webhooks to get notified when a user signs up
- React Native SDK Reference for the full API documentation

