# Auth0 Expo

> Use when adding authentication to Expo (React Native) mobile apps — login, logout, user sessions, protected routes, biometrics, or token management. Integrates react-native-auth0 SDK with Expo Config Plugin for native iOS/Android builds. Trigger for any Expo project needing Auth0, including app.json plugin config, custom scheme setup, or credential management. Do NOT use for bare React Native CLI projects (use auth0-react-native), React web apps (use auth0-react), Next.js (use auth0-nextjs), or backend APIs.

- Skill: `tomevault-io/auth0-expo` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add tomevault-io/auth0-expo`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tomevault-io/auth0-expo/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- License: Proprietary
- Author: tomevault-io (https://skillmd.com/u/tomevault-io)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/tomevault-io/auth0-expo

---


# Auth0 Expo Integration

Add authentication to Expo (React Native) applications using `react-native-auth0` with the Expo Config Plugin.

> **Agent instruction:** Before providing SDK setup instructions, fetch the latest release version by running:
> ```bash
> gh api repos/auth0/react-native-auth0/releases/latest --jq '.tag_name'
> ```
> Use the returned version in all dependency lines instead of any hardcoded version below. If the command fails, fall back to checking https://github.com/auth0/react-native-auth0/releases.

## Prerequisites

- Expo SDK 53 or higher (react-native-auth0 v5.x requires Expo 53+)
- React 19 and React Native 0.78.0 or higher
- Node.js 20+ (for bootstrap script automation)
- Auth0 account with a **Native** application configured
- If Auth0 is not set up yet, use the `auth0-quickstart` skill first
- **Not compatible with Expo Go** — requires custom development client or EAS Build

## When NOT to Use

| Use Case | Recommended Skill |
|----------|------------------|
| Bare React Native CLI project (no Expo) | `auth0-react-native` |
| React web SPA (Vite/CRA) | `auth0-react` |
| Next.js application | `auth0-nextjs` |
| Vue.js SPA | `auth0-vue` |
| Angular SPA | `auth0-angular` |
| Express.js backend | `auth0-express` |
| Native Android (Kotlin/Java) | `auth0-android` |
| Backend API (JWT validation) | `auth0-fastify-api` or `auth0-express` |

## Quick Start Workflow

> **Agent instruction:** First, check whether the user's prompt already includes both Auth0 **Client ID** and **Domain**.
> - If both are provided, skip the setup-choice question and proceed directly to **Step 2 (Verify Expo Dev Client)** using those values.
> - If either value is missing, ask the user using `AskUserQuestion`: _"How would you like to configure Auth0 for this Expo project?"_
>   - **Automatic setup (Recommended)** — runs a bootstrap script that creates the Auth0 app, database connection, callback URLs, and writes the plugin config to app.json
>   - **Manual setup** — the user provides their Auth0 Client ID and Domain
>
> Follow the matching section below based on their choice.

### 1. Configure Auth0

#### Automatic Setup

> **Agent instruction:** Run these quick checks before the bootstrap script. Do NOT run `auth0 login` from the agent — it is interactive and will hang.
>
> 1. **Check Node.js**: `node --version`. If missing or below 20, ask user: install (`brew install node`) or switch to manual setup.
> 2. **Check Auth0 CLI**: `command -v auth0`. If missing, ask user: install (`brew install auth0/auth0-cli/auth0`) or switch to manual setup.
> 3. **Check Auth0 login**: `auth0 tenants list --csv --no-input 2>&1`. If it fails or returns empty:
>    - Tell the user: _"Please run `auth0 login` in your terminal and let me know when done."_
>    - Wait for the user to confirm, then re-run the check to verify.
> 4. **Confirm active tenant**: Parse the `→` line from the CSV output to identify the active tenant domain. Tell the user: _"Your active Auth0 tenant is: `<domain>`. Is this the correct tenant?"_
>    - If yes, proceed.
>    - If no, ask the user to run `auth0 tenants use <tenant-domain>` in their terminal, then re-run step 3 to confirm the new active tenant.
>
> Once confirmed, run the bootstrap script:
> ```bash
> cd <path-to-skill>/auth0-expo/scripts
> npm install
> node bootstrap.mjs <path-to-expo-project>
> ```
>
> The script validates the Expo project, creates a Native Auth0 application, sets up a database connection, and writes the plugin config to app.json. The agent should NOT handle client_id or domain manually.
>
> If the script fails due to session expiry, ask the user to run `auth0 login` again, then re-run the script. For other failures, fall back to **Manual Setup** below.
>
> After the script completes, proceed to **Step 2 (Verify Expo Dev Client)**.

#### Manual Setup (User-Provided Credentials)

> **Agent instruction:** Ask the user for their Auth0 credentials using `AskUserQuestion`:
>
> "I need your Auth0 credentials to set up authentication. Please provide:
>
> 1. **Auth0 Domain** (e.g., `your-tenant.us.auth0.com`)
> 2. **Client ID** (a 32-character alphanumeric string)
>
> You can find both in the [Auth0 Dashboard](https://manage.auth0.com/) under **Applications > Applications > your app > Settings**. If you don't have an Auth0 app yet, create one with type **Native** and copy the domain and client ID from the settings page."
>
> Then write the configuration to app.json and proceed to **Step 2**.

### 2. Verify Expo Dev Client

> **Agent instruction:** Before installing the Auth0 SDK, check if the project has `expo-dev-client` installed. Read the project's `package.json` and look for `expo-dev-client` in `dependencies` or `devDependencies`.
>
> - **If `expo-dev-client` is found:** Proceed to step 3.
> - **If `expo-dev-client` is NOT found:** Use `AskUserQuestion` with the following message:
>
>   "The `react-native-auth0` SDK requires a custom Expo development client — it does **not** work with Expo Go. Your project does not have `expo-dev-client` installed.
>
>   How would you like to proceed?
>   1. **Install it for me** — I'll run `npx expo install expo-dev-client` and continue setup
>   2. **I'll set it up myself** — skip this step and continue to Auth0 SDK installation"
>
>   If the user picks option 1, run:
>   ```bash
>   npx expo install expo-dev-client
>   ```
>   Then proceed to step 3. If option 2, proceed to step 3 directly.

### 3. Install SDK

```bash
npx expo install react-native-auth0
```

### 4. Configure Expo Config Plugin

Add the react-native-auth0 plugin to `app.json` (or `app.config.js`) with your Auth0 domain and a custom scheme. Also ensure `bundleIdentifier` (iOS) and `package` (Android) are set:

```json
{
  "expo": {
    "ios": { "bundleIdentifier": "com.yourcompany.yourapp" },
    "android": { "package": "com.yourcompany.yourapp" },
    "plugins": [
      ["react-native-auth0", {
        "domain": "YOUR_AUTH0_DOMAIN",
        "customScheme": "YOUR_CUSTOM_SCHEME"
      }]
    ]
  }
}
```

The `customScheme` must be all lowercase with no special characters (e.g., `auth0sample`). See [**Setup Guide**](./references/setup.md) for HTTPS callbacks, multiple domains, EAS Build, and secret management.

> **Agent instruction:** If you used automatic setup (Step 1), the bootstrap script already wrote the plugin config to app.json — verify it's correct but do not overwrite it. If you used manual setup, write the config now using the user-provided domain and a custom scheme.

### 5. Configure Callback URLs

Add to **Allowed Callback URLs** and **Allowed Logout URLs** in the [Auth0 Dashboard](https://manage.auth0.com/):

```text
YOUR_CUSTOM_SCHEME://YOUR_AUTH0_DOMAIN/ios/YOUR_BUNDLE_ID/callback,
YOUR_CUSTOM_SCHEME://YOUR_AUTH0_DOMAIN/android/YOUR_PACKAGE/callback
```

All values must be **lowercase** with **no trailing slash**. For HTTPS callback URLs (App Links / Universal Links), see [Setup Guide](./references/setup.md#using-https-callback-urls-android-app-links).

### 6. Add Authentication with Auth0Provider

Wrap your app with `Auth0Provider` and use the `useAuth0` hook:

> **Agent instruction:** Before adding new UI elements, search the project for existing click handlers for login, logout, sign-in, or sign-out buttons. If existing handlers are found, hook the Auth0 code into them. Only create new buttons if no existing handlers are found.

```typescript
import React from 'react';
import { Auth0Provider, useAuth0 } from 'react-native-auth0';
import { View, Button, Text, ActivityIndicator } from 'react-native';

function HomeScreen() {
  const { authorize, clearSession, user, isLoading, error } = useAuth0();

  const login = async () => {
    try {
      await authorize(
        { scope: 'openid profile email' },
        { customScheme: 'YOUR_CUSTOM_SCHEME' }
      );
    } catch (e) {
      console.error('Login error:', e);
    }
  };

  const logout = async () => {
    try {
      await clearSession({ customScheme: 'YOUR_CUSTOM_SCHEME' });
    } catch (e) {
      console.error('Logout error:', e);
    }
  };

  if (isLoading) {
    return <ActivityIndicator size="large" />;
  }

  return (
    <View>
      {user ? (
        <>
          <Text>Welcome, {user.name}!</Text>
          <Text>{user.email}</Text>
          <Button title="Log Out" onPress={logout} />
        </>
      ) : (
        <Button title="Log In" onPress={login} />
      )}
      {error && <Text>{error.message}</Text>}
    </View>
  );
}

export default function App() {
  return (
    <Auth0Provider
      domain="YOUR_AUTH0_DOMAIN"
      clientId="YOUR_AUTH0_CLIENT_ID"
    >
      <HomeScreen />
    </Auth0Provider>
  );
}
```

### 7. Build & Verify

> **Agent instruction:** After completing the integration, build the project to verify it compiles:
> ```bash
> npx expo prebuild --clean
> npx expo run:ios
> # or
> npx expo run:android
> ```
> If the build fails, analyze the error output. Common integration build failures include:
> - **"Invariant Violation: Native module cannot be null"**: Using Expo Go instead of a development build — run `npx expo run:ios` or `npx expo run:android` instead of `npx expo start`
> - **Plugin not applied**: Missing `react-native-auth0` in app.json plugins array — verify the plugin configuration
> - **Pod install fails (iOS)**: Run `npx expo prebuild --clean` to regenerate native projects
> - **Manifest merge failure (Android)**: Conflicting auth0Domain placeholder — ensure only the config plugin sets the domain
>
> Re-run the build after each fix. Track the number of build-fix iterations.
>
> **Failcheck:** If the build still fails after 5–6 fix attempts, stop and ask the user using `AskUserQuestion`:
> _"The build is still failing after several fix attempts. How would you like to proceed?"_
> - **Let the skill continue fixing iteratively**
> - **Fix it manually** — show the remaining errors
> - **Skip build verification** — proceed without a successful build

## Detailed Documentation

- **[Setup Guide](./references/setup.md)** — Dev client requirement, automated setup, Expo config plugin, callback URLs, EAS Build, secret management
- **[Integration Patterns](./references/integration.md)** — Login/logout, credential management, biometric auth, token refresh, organizations, DPoP, error handling
- **[API Reference & Testing](./references/api.md)** — Configuration options, useAuth0 hook API, testing checklist, common issues, security

## Common Mistakes

| Mistake | Fix |
|---------|-----|
| Using Expo Go instead of development build | react-native-auth0 requires native code. Use `npx expo run:ios` / `npx expo run:android` or create a development build with EAS. |
| Missing `customScheme` in authorize/clearSession calls | Pass `{ customScheme: 'your-scheme' }` as the second argument to `authorize()` and `clearSession()`. Must match the value in app.json plugin config. |
| Callback URL mismatch | Ensure callback URL is all lowercase, no trailing slash, and matches Auth0 Dashboard exactly: `{customScheme}://{domain}/ios/{bundleId}/callback` |
| App type not set to Native | The Auth0 application must be type **Native** in the Dashboard, not SPA or Regular Web. |
| Missing bundleIdentifier or package in app.json | Both `expo.ios.bundleIdentifier` and `expo.android.package` must be set in app.json for callback URLs to work. |
| Forgot to wrap app with Auth0Provider | All components using `useAuth0()` must be children of `Auth0Provider`. |
| Using react-native-auth0 v5.x with Expo < 53 | Version 5.x requires Expo 53+. Use v4.x for older Expo versions. |
| Not testing on physical device | Biometric authentication (Face ID, fingerprint) only works on a physical device, not simulators. Always test the full auth flow on a real device before release. |

## Related Skills

- [auth0-quickstart](/auth0-quickstart) — Set up an Auth0 account and application
- [auth0-react-native](/auth0-react-native) — Bare React Native CLI projects
- [auth0-mfa](/auth0-mfa) — Configure multi-factor authentication

## References

- [Auth0 Expo Quickstart](https://auth0.com/docs/quickstart/native/react-native-expo/interactive)
- [react-native-auth0 GitHub Repository](https://github.com/auth0/react-native-auth0)
- [react-native-auth0 API Documentation](https://auth0.github.io/react-native-auth0/)
- [Expo Sample App](https://github.com/auth0-samples/auth0-react-native-sample/tree/master/00-Login-Expo)
- [EXAMPLES.md](https://github.com/auth0/react-native-auth0/blob/master/EXAMPLES.md)

---
> Source: [auth0/docs-v2](https://github.com/auth0/docs-v2) — distributed by [TomeVault](https://tomevault.io).
<!-- tomevault:4.0:skill_md:2026-05-22 -->

