## Documentation Index

Fetch the complete documentation index at: [/llms.txt](/content/llms.txt)

Use this file to discover all available pages before exploring further.

This Quickstart is for the React Native framework. To integrate Auth0 into your Expo application, refer to the [Expo Quickstart](/content/docs/quickstart/native/react-native-expo/interactive/index.html).

Use AI to integrate Auth0

If you use an AI coding assistant like Claude Code, Cursor, or GitHub Copilot, you can add Auth0 authentication automatically in minutes using [agent skills](https://agentskills.io/home).**Install:**

```
npx skills add auth0/agent-skills --skill auth0
```

**Then ask your AI assistant:**

```
Add Auth0 authentication to my React Native app
```

Your AI assistant will automatically create your Auth0 application, fetch credentials, install `react-native-auth0`, configure native dependencies, and set up your authentication flow. [Full agent skills documentation →](/content/docs/quickstart/agent-skills/index.html)

## Get Started

1. Create a new React Native project

Create a new React Native project for this quickstart.**In your terminal:**

```
npx @react-native-community/cli init Auth0ReactNativeSample
cd Auth0ReactNativeSample
```

Configure your project with:

- **Name**: `Auth0ReactNativeSample`
- **Package name**: `com.auth0.samples.reactnative`

This creates a React Native app with the latest stable version. The Auth0 SDK requires React Native 0.78.0+ and React 19.0.0+.

2. Install the Auth0 SDK

Add the Auth0 React Native SDK to your project.

```
npm install react-native-auth0
```

For iOS, install the native dependencies:

```
cd ios && pod install && cd ..
```

The SDK auto-links on both platforms. The `pod install` step installs the required iOS native modules (Auth0.swift, JWTDecode, SimpleKeychain).

3. Configure your Auth0 Application

Create and configure an Auth0 application to work with your React Native app.

1. Head to the [Auth0 Dashboard](https://manage.auth0.com/dashboard/)
2. Click on **Applications** > **Applications** > **Create Application**
3. In the popup, enter a name for your app (e.g., `Auth0 React Native Sample`), select `Native` as the app type and click **Create**
4. Switch to the **Settings** tab on the Application Details page
5. Note your **Domain** and **Client ID** values

**Allowed Callback URLs:**

```
org.reactjs.native.example.auth0reactnativesample.auth0://{yourDomain}/ios/org.reactjs.native.example.auth0reactnativesample/callback,
com.auth0reactnativesample.auth0://{yourDomain}/android/com.auth0reactnativesample/callback
```

**Allowed Logout URLs:**

Replace `{yourDomain}` with your actual Auth0 domain (e.g., `dev-abc123.us.auth0.com`).

**Allowed Callback URLs** are a critical security measure to ensure users are safely returned to your application after authentication. Without a matching URL, the login process will fail, and users will be blocked by an Auth0 error page instead of accessing your app.

**Allowed Logout URLs** are essential for providing a seamless user experience upon signing out. Without a matching URL, users will not be redirected back to your application after logout and will instead be left on a generic Auth0 page. The URL scheme includes `.auth0` after your bundle identifier to ensure the callback is routed to your specific app. For this quickstart, the bundle identifier is `org.reactjs.native.example.auth0reactnativesample`.

**Important**: The callback URL scheme must include `.auth0` after your bundle identifier (e.g., `org.reactjs.native.example.auth0reactnativesample.auth0://`). This is required for the SDK to properly handle the authentication callback.

4. Configure Native Platforms

Configure both iOS and Android to handle the authentication callback.

**Android Configuration:** Open `android/app/build.gradle` and add the manifest placeholders inside `defaultConfig`:

```
android {
    defaultConfig {
        applicationId "com.auth0reactnativesample"
        // ... other config

// Add Auth0 manifest placeholders
        manifestPlaceholders = [\
            auth0Domain: "{yourDomain}",\
            auth0Scheme: "${applicationId}.auth0"\
        ]
    }
}
```

Replace `{yourDomain}` with your Auth0 domain (e.g., `dev-abc123.us.auth0.com`).

**iOS Configuration:**

- AppDelegate.mm (Objective-C)
- AppDelegate.swift (Swift)

Open `ios/Auth0ReactNativeSample/AppDelegate.mm` and add the URL handling method:

```
#import <React/RCTLinkingManager.h>

// Add this method inside the @implementation block
- (BOOL)application:(UIApplication *)app
            openURL:(NSURL *)url
            options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options
{
  return [RCTLinkingManager application:app openURL:url options:options];
}
```

Open `ios/Auth0ReactNativeSample/AppDelegate.swift` and add the URL handling method:

```
import React

// Add this method inside the AppDelegate class
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
  return RCTLinkingManager.application(app, open: url, options: options)
}
```

Open `ios/Auth0ReactNativeSample/Info.plist` and add the URL scheme. Add this before the closing `</dict>` tag:

```
<key>CFBundleURLTypes</key>
<array>
  <dict>
    <key>CFBundleTypeRole</key>
    <string>None</string>
    <key>CFBundleURLName</key>
    <string>auth0</string>
    <key>CFBundleURLSchemes</key>
    <array>
      <string>$(PRODUCT_BUNDLE_IDENTIFIER).auth0</string>
    </array>
  </dict>
</array>
```

The URL scheme uses your bundle identifier with `.auth0` appended. This ensures the callback is routed to your specific app after authentication completes in the browser.

5. Setup App Component

Setup your main app component based on your chosen implementation approach.

- Hooks-based (with Provider)

- Class-based (without Provider)

Replace the contents of `App.tsx` and wrap your application with the `Auth0Provider` component:

```
import React from 'react';
import {Auth0Provider} from 'react-native-auth0';
import {SafeAreaView, StyleSheet} from 'react-native';
import MainScreen from './src/MainScreen';

const App = () => {
  return (
    <Auth0Provider
      domain="{yourDomain}"
      clientId="{yourClientId}">
      <SafeAreaView style={styles.container}>
        <MainScreen />
      </SafeAreaView>
    </Auth0Provider>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
  },
});

export default App;
```

Replace `{yourDomain}` with your Auth0 domain and `{yourClientId}` with your Client ID from the Auth0 Dashboard.

The `Auth0Provider` initializes the SDK and provides authentication context to all child components via the `useAuth0` hook.

Replace the contents of `App.tsx` with a simple container for your class-based component:

```
import React from 'react';
import {SafeAreaView, StyleSheet} from 'react-native';
import MainScreen from './src/MainScreen';

const App = () => {
  return (
    <SafeAreaView style={styles.container}>
      <MainScreen />
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
  },
});

export default App;
```

The class-based approach doesn’t require the `Auth0Provider` since it uses the `Auth0` class instance directly. The Auth0 configuration will be in the MainScreen component.

6. Implement Login and Logout

Create a screen component that handles login and logout. You can choose between a hooks-based approach (recommended) or a class-based approach.

- Hooks-based (Recommended)

- Class-based

Create `src/MainScreen.tsx` using the `useAuth0` hook:

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

const MainScreen = () => {
  const {authorize, clearSession, user, isLoading} = useAuth0();

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

const logout = async () => {
    try {
      await clearSession();
    } catch (e) {
      console.error(e);
    }
  };

if (isLoading) {
    return (
      <View style={styles.container}>
        <ActivityIndicator size="large" color="#0066cc" />
        <Text style={styles.loadingText}>Loading...</Text>
      </View>
    );
  }

return (
    <View style={styles.container}>
      <Text style={styles.title}>Auth0 React Native</Text>

{user ? (
        <View style={styles.profileContainer}>
          {user.picture && (
            <Image source={{uri: user.picture}} style={styles.avatar} />
          )}
          <Text style={styles.welcomeText}>Welcome, {user.name}!</Text>
          <Text style={styles.emailText}>{user.email}</Text>
          <View style={styles.buttonContainer}>
            <Button title="Log Out" onPress={logout} color="#dc3545" />
          </View>
        </View>
      ) : (
        <View style={styles.loginContainer}>
          <Text style={styles.subtitle}>
            Tap the button below to log in
          </Text>
          <View style={styles.buttonContainer}>
            <Button title="Log In" onPress={login} color="#0066cc" />
          </View>
        </View>
      )}
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 20,
  },
  title: {
    fontSize: 28,
    fontWeight: 'bold',
    marginBottom: 20,
    color: '#333',
  },
  subtitle: {
    fontSize: 16,
    color: '#666',
    marginBottom: 30,
    textAlign: 'center',
  },
  loadingText: {
    marginTop: 10,
    fontSize: 16,
    color: '#666',
  },
  profileContainer: {
    alignItems: 'center',
  },
  avatar: {
    width: 100,
    height: 100,
    borderRadius: 50,
    marginBottom: 20,
  },
  welcomeText: {
    fontSize: 22,
    fontWeight: '600',
    marginBottom: 8,
    color: '#333',
  },
  emailText: {
    fontSize: 16,
    color: '#666',
    marginBottom: 30,
  },
  loginContainer: {
    alignItems: 'center',
  },
  buttonContainer: {
    width: 200,
    marginTop: 10,
  },
});

export default MainScreen;
```

Create `src/MainScreen.tsx` using the `Auth0` class directly:

```
import React, {Component} from 'react';
import {
  View,
  Text,
  Button,
  StyleSheet,
  ActivityIndicator,
  Image,
} from 'react-native';
import Auth0, {Credentials} from 'react-native-auth0';

const auth0 = new Auth0({
  domain: '{yourDomain}',
  clientId: '{yourClientId}',
});

interface User {
  name?: string;
  email?: string;
  picture?: string;
}

interface MainScreenState {
  user: User | null;
  isLoading: boolean;
}

class MainScreen extends Component<{}, MainScreenState> {
  constructor(props: {}) {
    super(props);
    this.state = {
      user: null,
      isLoading: true,
    };
  }

async componentDidMount() {
    await this.checkAuthStatus();
  }

checkAuthStatus = async () => {
    try {
      const hasValidCredentials = await auth0.credentialsManager.hasValidCredentials();
      if (hasValidCredentials) {
        const credentials = await auth0.credentialsManager.getCredentials();
        const userInfo = await auth0.auth.userInfo({token: credentials.accessToken});
        this.setState({user: userInfo, isLoading: false});
      } else {
        this.setState({isLoading: false});
      }
    } catch (e) {
      console.error(e);
      this.setState({isLoading: false});
    }
  };

login = async () => {
    try {
      const credentials: Credentials = await auth0.webAuth.authorize({
        scope: 'openid profile email',
      });

await auth0.credentialsManager.saveCredentials(credentials);
      const userInfo = await auth0.auth.userInfo({token: credentials.accessToken});
      this.setState({user: userInfo});
    } catch (e) {
      console.error(e);
    }
  };

logout = async () => {
    try {
      await auth0.webAuth.clearSession();
      await auth0.credentialsManager.clearCredentials();
      this.setState({user: null});
    } catch (e) {
      console.error(e);
    }
  };

render() {
    const {user, isLoading} = this.state;

return (
      <View style={styles.container}>
        <Text style={styles.title}>Auth0 React Native</Text>

{user ? (
          <View style={styles.profileContainer}>
            {user.picture && (
              <Image source={{uri: user.picture}} style={styles.avatar} />
            )}
            <Text style={styles.welcomeText}>Welcome, {user.name}!</Text>
            <Text style={styles.emailText}>{user.email}</Text>
            <View style={styles.buttonContainer}>
              <Button title="Log Out" onPress={this.logout} color="#dc3545" />
            </View>
          </View>
        ) : (
          <View style={styles.loginContainer}>
            <Text style={styles.subtitle}>
              Tap the button below to log in
            </Text>
            <View style={styles.buttonContainer}>
              <Button title="Log In" onPress={this.login} color="#0066cc" />
            </View>
          </View>
        )}
      </View>
    );
  }
}

export default MainScreen;
```

Replace `{yourDomain}` with your Auth0 domain and `{yourClientId}` with your Client ID from the Auth0 Dashboard.

The `authorize()` method (hooks) or `auth0.webAuth.authorize()` (class) opens Auth0’s Universal Login in a secure browser (ASWebAuthenticationSession on iOS, Chrome Custom Tabs on Android). The `clearSession()` method logs the user out and clears both the browser session and stored credentials.

7. Run your app

Build and run your React Native application on a device or emulator.

**For iOS (requires macOS):**

```
npx react-native run-ios
```

**For Android:**

```
npx react-native run-android
```

**Expected flow:**

1. App launches showing “Log In” button
2. Tap **Log In** → Browser opens with Auth0 Universal Login
3. Complete login (sign up or sign in)
4. Browser closes → Returns to app automatically
5. User profile displays with name, email, and avatar

iOS Simulator requires a valid Apple Developer account for ASWebAuthenticationSession. For testing on simulator without an account, use a physical device or Android emulator instead.

**Checkpoint** You should now have a fully functional Auth0 login experience running on your device or emulator. The app uses secure browser authentication and automatically manages credentials.

## Troubleshooting & Advanced

Common Issues & Solutions

### ”Callback URL mismatch” error

**Solution:**

1. Verify the exact URL (including `.auth0` suffix) is in **Allowed Callback URLs** in your Auth0 Dashboard
2. Ensure both iOS and Android URLs are added
3. Check that `{yourDomain}` is replaced with your actual Auth0 domain

### App doesn’t return after login (iOS)

**Fix:**

1. Check `Info.plist` has the `CFBundleURLSchemes` entry with `$(PRODUCT_BUNDLE_IDENTIFIER).auth0`
2. Verify `AppDelegate.mm` includes the URL handling method
3. Ensure the URL scheme matches your bundle identifier

### Android build fails

**Fix:**

1. Add `auth0Domain` and `auth0Scheme` manifest placeholders to `build.gradle`
2. Sync project with Gradle files
3. Clean build: `./gradlew clean`

### ”PKCE not allowed” error

**Fix:**

1. Go to Auth0 Dashboard → Applications → Your Application
2. Change application type to **Native**
3. Save changes and try again

### Pod install fails (iOS)

**Fix:**

1. Update CocoaPods: `sudo gem install cocoapods`
2. Update pod repo: `pod install --repo-update`
3. If issues persist, delete `Podfile.lock` and `ios/Pods` folder, then run `pod install` again

### User cancelled error

Handle gracefully in your login function:

```
const login = async () => {
  try {
    await authorize({scope: 'openid profile email'});
  } catch (e) {
    if (e.message === 'a0.session.user_cancelled') {
      // User closed login screen - handle gracefully
      console.log('Login cancelled by user');
    } else {
      console.error('Login failed:', e);
    }
  }
};
```

### iOS Alert Dialog

On iOS, users see a permission dialog: _“App Name” Wants to Use “auth0.com” to Sign In_. This is expected behavior from `ASWebAuthenticationSession`. Users must tap **Continue** to proceed. To customize this behavior, you can use ephemeral sessions (disables SSO):

```
await authorize({scope: 'openid profile email'}, {ephemeralSession: true});
```

### Retrieving Access Tokens

Use the `getCredentials()` method to retrieve tokens for API calls:

```
import {useAuth0} from 'react-native-auth0';

const MyComponent = () => {
  const {getCredentials} = useAuth0();

const callApi = async () => {
    try {
      const credentials = await getCredentials();
      const response = await fetch('https://your-api.com/endpoint', {
        headers: {
          Authorization: `Bearer ${credentials.accessToken}`,
        },
      });
      // Handle response
    } catch (e) {
      console.error('Failed to get credentials', e);
    }
  };
};
```

Include the `offline_access` scope during login to receive a refresh token: `authorize({scope: 'openid profile email offline_access'})`. This enables automatic token renewal.

### Check Authentication Status on App Launch

Use `hasValidCredentials()` to check if the user is already logged in:

```
import {useAuth0} from 'react-native-auth0';
import {useEffect} from 'react';

const App = () => {
  const {hasValidCredentials, getCredentials} = useAuth0();

useEffect(() => {
    const checkAuth = async () => {
      const isLoggedIn = await hasValidCredentials();
      if (isLoggedIn) {
        const credentials = await getCredentials();
        // User is authenticated, load their data
      }
    };
    checkAuth();
  }, []);
};
```

## Production Deployment

### Before deploying to production

**Use HTTPS callback URLs** for enhanced security:

```
https://{yourDomain}/ios/{bundleId}/callback
https://{yourDomain}/android/{packageName}/callback
```

**Configure Android App Links** in Auth0 Dashboard:

- Settings → Advanced Settings → Device Settings
- Add your app’s SHA-256 fingerprint

**Configure iOS Universal Links:**

- Add Associated Domains capability in Xcode
- Add `webcredentials:{yourDomain}` to Associated Domains

**Enable biometric authentication** for sensitive apps using `localAuthenticationOptions` in `Auth0Provider`

**Review security settings** in Auth0 Dashboard:

- Enable **OIDC Conformant** in Advanced Settings
- Configure **Token Expiration** appropriately
- Set up **Brute Force Protection**
- Test on multiple devices and OS versions
- Implement proper error handling for network failures

- [Sample Application](https://github.com/auth0-samples/auth0-react-native-sample)
- [Migration Guide (v4 to v5)](https://github.com/auth0/react-native-auth0/blob/master/MIGRATION_GUIDE.md)
