Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs-staging.auth0-mintlify.app/llms.txt

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

Get Started

This quickstart demonstrates how to add Auth0 authentication to an Ionic React application with Capacitor. You’ll build a mobile-ready app with login, logout, and user profile features using the Auth0 React SDK and Capacitor’s native browser integration.
1

Create a new project

Create a new Ionic React app with Capacitor
npx ionic start auth0-ionic-react tabs --type=react --capacitor
Open the project
cd auth0-ionic-react
Make sure you’re using the @ionic/cli package (not the deprecated ionic package). If you see errors about --npm-client during project creation, update your CLI:
npm uninstall -g ionic
npm i -g @ionic/cli
If you already have an Ionic React app, make sure Capacitor is enabled. You can add it with ionic integrations enable capacitor and then npx cap init.
2

Install the Auth0 React SDK and Capacitor plugins

The Ionic starter template may scaffold react@19.0.0, which is not compatible with the Auth0 React SDK. First, ensure you have a supported React version:
npm install react@^19.0.1 react-dom@^19.0.1
Then install the Auth0 SDK and Capacitor plugins:
npm install @auth0/auth0-react @capacitor/browser @capacitor/app && npx cap sync
Capacitor’s Browser plugin on iOS uses SFSafariViewController, which on iOS 11+ does not share cookies with Safari on the device. This means SSO will not work on those devices. If you need SSO, use a compatible plugin that uses ASWebAuthenticationSession.
3

Setup your Auth0 App

Next up, you need to create a new app on your Auth0 tenant and add the environment variables to your project.You have three options to set up your Auth0 app: use the Quick Setup tool (recommended), run a CLI command, or configure manually via the Dashboard.
Throughout this quickstart, YOUR_PACKAGE_ID is your application’s package ID. This is the appId field in your capacitor.config.ts file (e.g. io.ionic.starter). See Capacitor’s Config schema for more info.
Verify your .env file exists: cat .env (Mac/Linux) or type .env (Windows)
4

Configure the Auth0Provider

Open src/main.tsx and wrap the App component with the Auth0Provider. The mobile-specific settings useRefreshTokens and useRefreshTokensFallback are required for Ionic apps on iOS and Android.
src/main.tsx
import React from 'react';
import { createRoot } from 'react-dom/client';
import App from './App';
import { Auth0Provider } from '@auth0/auth0-react';

// Must match the appId in your capacitor.config.ts
const appId = 'io.ionic.starter';

createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <Auth0Provider
      domain={import.meta.env.VITE_AUTH0_DOMAIN}
      clientId={import.meta.env.VITE_AUTH0_CLIENT_ID}
      useRefreshTokens={true}
      useRefreshTokensFallback={false}
      authorizationParams={{
        redirect_uri: `${appId}://${import.meta.env.VITE_AUTH0_DOMAIN}/capacitor/${appId}/callback`
      }}
    >
      <App />
    </Auth0Provider>
  </React.StrictMode>
);
  • useRefreshTokens: Required for Ionic on Android and iOS. Mobile browsers block third-party cookies, so the SDK uses refresh tokens instead of iframe-based silent authentication.
  • useRefreshTokensFallback: Must be false to prevent the SDK from attempting iframe-based silent auth, which is not available on mobile.
  • authorizationParams.redirect_uri: Uses your package ID as a custom URL scheme so the OS can route the Auth0 callback back to your app.
To persist authentication after closing and reopening the application, you may want to set cacheLocation to localstorage, but be aware of the risks of storing tokens in localstorage. On Capacitor, localstorage should be treated as transient — the OS may clear it unexpectedly. See Capacitor’s guidance on storage.We recommend against using Capacitor’s Preferences plugin to store tokens, as it is backed by UserDefaults (iOS) and SharedPreferences (Android), which are not encrypted and could be synced to the cloud. The SDK supports custom cache implementations if you need a more secure and persistent storage mechanism.
5

Create Login, Logout, Profile, and Callback Handler

Create files
touch src/LoginButton.tsx && touch src/LogoutButton.tsx && touch src/Profile.tsx
And add the following code snippetsThe openUrl callback in LoginButton and LogoutButton uses Capacitor’s Browser plugin to open the Auth0 login and logout pages in the device’s system browser component, rather than navigating away from the app entirely.The App component listens for the appUrlOpen event, which fires when Auth0 redirects back to your app using the custom URL scheme. It calls handleRedirectCallback to exchange the authorization code for tokens, then closes the browser.
By default, the SDK’s loginWithRedirect method uses window.location.href to navigate to the login page, which opens the device’s default browser application. Setting openUrl to use Browser.open keeps the authentication flow within your app’s context for a better user experience.
6

Run your app

Test in the browser first
ionic serve
When running in the browser with ionic serve, the custom URL scheme redirect (io.ionic.starter://...) won’t work because browsers cannot handle custom URL schemes. For browser testing, temporarily change redirect_uri to http://localhost:8100 in src/main.tsx and add http://localhost:8100 to your Auth0 app’s Allowed Callback URLs and Allowed Logout URLs in the Dashboard. Remember to revert this change before building for native.
To run on a device or simulator, first add the native platforms:
npx cap add ios
npx cap add android
Then build, sync, and run:
ionic build && npx cap sync && npx cap run ios
You must add native platforms with npx cap add before you can run on them. This only needs to be done once per platform. After that, npx cap sync copies your built web assets and updates native plugins.
CheckpointYou should now have a fully functional Auth0 login running in your Ionic app. When running on a device, tapping “Log in” opens the Auth0 Universal Login Page in the system browser, and after authenticating, you’re redirected back to your app with the user’s profile displayed.

Advanced Usage

For Auth0 callbacks to work on devices, register your package ID as a custom URL scheme on each platform.iOS — add to ios/App/App/Info.plist:
ios/App/App/Info.plist
<key>CFBundleURLTypes</key>
<array>
  <dict>
    <key>CFBundleURLSchemes</key>
    <array>
      <string>io.ionic.starter</string>
    </array>
  </dict>
</array>
Android — add an intent filter inside the main <activity> in android/app/src/main/AndroidManifest.xml:
android/app/src/main/AndroidManifest.xml
<intent-filter>
  <action android:name="android.intent.action.VIEW" />
  <category android:name="android.intent.category.DEFAULT" />
  <category android:name="android.intent.category.BROWSABLE" />
  <data android:scheme="io.ionic.starter" />
</intent-filter>
Replace io.ionic.starter with your actual appId from capacitor.config.ts.
To learn more, read Defining a Custom URL Scheme for iOS, or Create Deep Links to App Content for Android.
Use Auth0’s authentication state to protect specific routes in your Ionic application:
src/App.tsx
import { useAuth0, withAuthenticationRequired } from '@auth0/auth0-react';
import { IonReactRouter } from '@ionic/react-router';
import { IonRouterOutlet } from '@ionic/react';
import { Route, Redirect } from 'react-router-dom';
import HomePage from './pages/Home';
import DashboardPage from './pages/Dashboard';

const ProtectedRoute = ({ component, ...args }: any) => {
  const Component = withAuthenticationRequired(component, {
    onRedirecting: () => <div className="ion-padding">Loading...</div>,
  });
  return <Route {...args} render={() => <Component />} />;
};

const App: React.FC = () => {
  // ... callback handler from previous step

  return (
    <IonApp>
      <IonReactRouter>
        <IonRouterOutlet>
          <Route exact path="/home" component={HomePage} />
          <ProtectedRoute exact path="/dashboard" component={DashboardPage} />
          <Route exact path="/">
            <Redirect to="/home" />
          </Route>
        </IonRouterOutlet>
      </IonReactRouter>
    </IonApp>
  );
};
The withAuthenticationRequired HOC automatically redirects unauthenticated users to the Auth0 login page when they try to access a protected route.
Configure your Auth0Provider to include an API audience and use the getAccessTokenSilently method to get access tokens for your backend:
src/main.tsx
<Auth0Provider
  domain={import.meta.env.VITE_AUTH0_DOMAIN}
  clientId={import.meta.env.VITE_AUTH0_CLIENT_ID}
  useRefreshTokens={true}
  useRefreshTokensFallback={false}
  authorizationParams={{
    redirect_uri: `${appId}://${import.meta.env.VITE_AUTH0_DOMAIN}/capacitor/${appId}/callback`,
    audience: "YOUR_API_IDENTIFIER"
  }}
>
  <App />
</Auth0Provider>
Then make authenticated API calls from your components:
src/ApiCall.tsx
import { useState } from 'react';
import { useAuth0 } from '@auth0/auth0-react';
import { IonButton, IonText } from '@ionic/react';

const ApiCall: React.FC = () => {
  const { getAccessTokenSilently } = useAuth0();
  const [result, setResult] = useState<string | null>(null);

  const callApi = async () => {
    try {
      const token = await getAccessTokenSilently();

      const response = await fetch('https://your-api.example.com/protected', {
        headers: {
          Authorization: `Bearer ${token}`
        }
      });

      const data = await response.json();
      setResult(JSON.stringify(data, null, 2));
    } catch (error) {
      console.error('API call failed:', error);
    }
  };

  return (
    <div className="ion-padding">
      <IonButton onClick={callApi}>Call Protected API</IonButton>
      {result && (
        <IonText>
          <pre>{result}</pre>
        </IonText>
      )}
    </div>
  );
};

export default ApiCall;