Zum Hauptinhalt springen

So meldest du dich mit Auth0 über Capacitor an

Auth0-Login für eine Capacitor 8 App mit OIDC und PKCE hinzufügen: Auth0 Dashboard-Setup, Callback-URLs, API Audience, Refresh Tokens, Logout und Troubleshooting.

Auth0 Universal Login, geöffnet über den Systembrowser in einer Capacitor App

Um sich mit Auth0 in einer Capacitor App anzumelden, erstelle ein Nativ App in Auth0, registriere eine Custom-Scheme-Callback-URL wie zum Beispiel com.example.app://oauth/auth0, und führe den OpenID Connect Authorization code Flow mit PKCE über einen System-Browser aus. Mit @capgo/capacitor-social-login das ist ein initialize Aufruf mit deinen Auth0-Endpoints und ein SocialLogin.login({ provider: 'oauth2', options: { providerId: 'auth0' } }).

Dieser Guide deckt die Auth0 Dashboard-Einstellungen, den Client code für iOS, Android und Web, API Access Tokens, Refresh Tokens, Logout sowie die gängigsten Fehler ab. Er wurde für Capacitor 8 (Stand Oktober 2026) erstellt.

So funktioniert der Auth0 Flow in Capacitor

Auth0 hostet die Login-Seite (Universal Login). Deine App sieht das Passwort nie. Der Flow sieht so aus:

  1. Die App generiert einen PKCE Verifier und Challenge und öffnet dann https://YOUR_TENANT/authorize in einem sicheren Browser.
  2. Der User loggt sich ein (Passwort, Social Login, Passkey, MFA – je nachdem, was du in Auth0 konfiguriert hast).
  3. Auth0 leitet zur Callback-URL mit einem einmaligen code.
  4. Die App tauscht den code und den PKCE Verifier bei /oauth/token für einen ID-Token, einen Access-Token und optional einen Refresh-Token.

Der verwendete Browser hängt von der Plattform ab:

Plattform Browser Callback-Handling
iOS ASWebAuthenticationSession Vom System gehandelt, keine Info.plist Änderung
Android Standardmäßig Embedded WebView oder Chrome Custom Tabs mit androidUseCustomTabs: true Custom Tabs benötigen einen Intent-Filter
Web Popup (Standard) oder Full-Page-Redirect handleRedirectCallback() auf der Rückkehrseite

Nutze unter Android Custom Tabs. Sie teilen Cookies mit Chrome, unterstützen Passkeys und Passwort-Manager und folgen RFC 8252 (OAuth für native Apps), was Auth0 erwartet.

Schritt 1: Auth0-App einrichten

  1. Im Auth0 Dashboard, gehe zu Anwendungen > Anwendungen > Anwendung erstellen.
  2. Wähle Native und erstelle sie.
  3. Auf der Einstellungen Tab, beachte die Domain sein (zum Beispiel example.eu.auth0.com) und die Client-ID.
  4. Unter Credentials, prüfe, ob die Authentifizierungsmethode Keineist. Das ist die Public-Client-Einstellung für PKCE.

Callback- und Logout-URLs

Diese Felder ausfüllen Einstellungen > Application URIs:

Feld Wert für Mobile Wert für Web
Zulässige Callback-URLs com.example.app://oauth/auth0 https://app.example.com/auth/callback
Zulässige Logout-URLs com.example.app://oauth/logout https://app.example.com/
Zulässige Web-Origins Nicht erforderlich https://app.example.com

Mehrere Werte durch Komma trennen. Nutze dein Capacitor appId als Scheme. Ein Reverse-Domain-Scheme verhindert Kollisionen mit anderen Apps. Falls du auch einen Web-Build bereitstellst, erstellen viele Teams eine separate Single-Page-Application in Auth0, damit sich die Web- und Mobile-Einstellungen nicht vermischen.

Refresh-Tokens

Falls die User angemeldet bleiben sollen:

  1. Unter Einstellungen > Refresh Token Rotation, aktiviere die Rotation. Jeder Refresh liefert einen neuen Refresh Token und invalidiert den alten.
  2. Lege eine absolute sowie eine Inaktivitäts-Lifetime fest, die zu deinem Produkt passt.
  3. Falls du deine eigene API aufrufst, öffne Applications > APIs > deine API > Settings und aktiviere Offline-Zugriff erlauben.
  4. Fordere den offline_access Scope in der App.

API Audience

Wenn dein Backend Auth0-Access-Tokens validiert, erstelle eine API unter Anwendungen > APIs mit einem Identifier wie https://api.example.com. Übergib diesen Identifier als audience. Ohne ihn ist das Access-Token nur für Auth0s /userinfo Endpoint gültig.

Schritt 2: Plugin installieren und konfigurieren

bun add @capgo/capacitor-social-login
bunx cap sync

Wenn Auth0 dein einziger Provider ist, deaktiviere die gebündelten Social SDKs, um die Binary klein zu halten:

// capacitor.config.ts
plugins: {
  SocialLogin: {
    providers: { google: false, facebook: false, apple: false, twitter: false },
  },
},

Die generische OAuth2-Engine ist nicht von diesen SDKs abhängig.

Android Intent-Filter für Custom Tabs

Füge das Callback-Schema zu MainActivity in 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="com.example.app" android:host="oauth" />
</intent-filter>

Das Capacitor Template setzt bereits android:launchMode="singleTask" auf MainActivity, das für den Redirect benötigt wird. Behalte es bei.

Schritt 3: Auth0-Provider initialisieren

import { Capacitor } from '@capacitor/core';
import { SocialLogin } from '@capgo/capacitor-social-login';

const AUTH0_DOMAIN = 'https://example.eu.auth0.com';
const isWeb = Capacitor.getPlatform() === 'web';

export async function initAuth() {
  await SocialLogin.initialize({
    oauth2: {
      auth0: {
        appId: 'YOUR_AUTH0_CLIENT_ID',
        authorizationBaseUrl: `${AUTH0_DOMAIN}/authorize`,
        accessTokenEndpoint: `${AUTH0_DOMAIN}/oauth/token`,
        resourceUrl: `${AUTH0_DOMAIN}/userinfo`,
        redirectUrl: isWeb
          ? 'https://app.example.com/auth/callback'
          : 'com.example.app://oauth/auth0',
        scope: 'openid profile email offline_access',
        pkceEnabled: true,
        additionalParameters: {
          audience: 'https://api.example.com',
        },
        logoutUrl: `${AUTH0_DOMAIN}/oidc/logout`,
        postLogoutRedirectUrl: isWeb
          ? 'https://app.example.com/'
          : 'com.example.app://oauth/logout',
        androidUseCustomTabs: true,
      },
    },
  });
}

Du kannst die expliziten Endpunkte durch issuerUrl: AUTH0_DOMAINersetzen. Das Plugin liest dann /.well-known/openid-configuration. Explizite Werte haben Vorrang vor automatisch erkannten, was bei der Nutzung einer Auth0 Custom Domain hilft.

Wenn du von Ionic Auth Connect migrierst, exportiert das Plugin auch SocialLoginAuthConnect mit einem auth0 Voreinstellung, die übernimmt domain, clientId, redirectUrl und audience. Siehe die Auth Connect Migrationsguide.

Schritt 4: Anmelden

import { SocialLogin } from '@capgo/capacitor-social-login';

export async function signInWithAuth0() {
  try {
    const { result } = await SocialLogin.login({
      provider: 'oauth2',
      options: { providerId: 'auth0' },
    });

    return {
      idToken: result.idToken,
      accessToken: result.accessToken?.token,
      expiresAt: result.accessToken?.expires,
      refreshToken: result.refreshToken,
      user: result.resourceData, // JSON from /userinfo
    };
  } catch (error: any) {
    if (error?.code === 'USER_CANCELLED') return null;
    throw error;
  }
}

Nützliche Login-Optionen:

  • prompt: 'login' erzwingt die Login-Seite, selbst wenn Auth0 noch ein Session-Cookie hat.
  • loginHint: 'user@example.com' füllt die E-Mail vor.
  • additionalParameters: { connection: 'google-oauth2' } überspringt Universal Login und nutzt direkt eine Verbindung.
  • additionalParameters: { screen_hint: 'signup' } öffnet den Registrierungsbildschirm.

Web-Redirect-Callback

Im Web benötigt der Standard-Popup-Flow keine Extras. Wenn du flow: 'redirect'nutzt, lies das Ergebnis auf der Callback-Seite aus:

const result = await SocialLogin.handleRedirectCallback();
if (result?.provider === 'oauth2') {
  console.log(result.result.idToken);
}

handleRedirectCallback funktioniert nur im Web und wird auf iOS und Android abgelehnt.

Schritt 5: ID-Token lesen und API aufrufen

Dekodieren Sie den ID-Token nur clientseitig zur Anzeige:

const { claims } = await SocialLogin.decodeIdToken({ idToken: result.idToken! });
console.log(claims.email, claims.name, claims.sub);

decodeIdToken prüft nicht die Signatur. Senden Sie für alles Sicherheitsrelevante den Access-Token an Ihr API und validieren Sie ihn dort:

import { createRemoteJWKSet, jwtVerify } from 'jose';

const jwks = createRemoteJWKSet(new URL('https://example.eu.auth0.com/.well-known/jwks.json'));

export async function verifyAuth0AccessToken(token: string) {
  const { payload } = await jwtVerify(token, jwks, {
    issuer: 'https://example.eu.auth0.com/', // Auth0 issuers end with a slash
    audience: 'https://api.example.com',
  });
  return payload; // payload.sub is the Auth0 user ID
}

Schritt 6: Access-Token erneuern

import { SocialLogin } from '@capgo/capacitor-social-login';

export async function getValidAccessToken() {
  const { isLoggedIn } = await SocialLogin.isLoggedIn({ provider: 'oauth2', providerId: 'auth0' });

  if (!isLoggedIn) {
    // access token expired: try the stored refresh token
    try {
      await SocialLogin.refresh({ provider: 'oauth2', options: { providerId: 'auth0' } });
    } catch {
      // refresh token expired, revoked or already rotated: sign in again
      const loginResult = await signInWithAuth0();
      if (!loginResult) throw new Error('Sign-in cancelled');
    }
  }

  const { accessToken } = await SocialLogin.getAuthorizationCode({
    provider: 'oauth2',
    providerId: 'auth0',
  });
  return accessToken;
}

refresh wird abgelehnt, wenn der Refresh-Token abgelaufen oder widerrufen wurde. Bei aktivierter Rotation schlägt auch ein bereits verwendeter Refresh-Token fehl; leiten Sie den User daher bei einer Ablehnung immer zum Login zurück.

refresh verwendet den beim Login gespeicherten Refresh-Token des Plugins. Wenn Sie den Refresh-Token selbst verwalten, rufen Sie SocialLogin.refreshToken({ provider: 'oauth2', providerId: 'auth0', refreshToken })auf, was die vollständige neue Token-Response zurückgibt. Speichern Sie bei aktivierter Rotation den neuen Refresh-Token jedes Mal.

Das Plugin speichert seine Token-Kopie im app-privaten Speicher. Falls Ihr Security-Review Keychain oder Keystore verlangt, speichern Sie den Refresh-Token mit NativeBiometric.setData({ key, value }) von @capgo/capacitor-native-biometric und übergeben Sie ihn an refreshToken dich selbst. Unsere Anleitung zur sicheren Token-Speicherung vergleicht die Optionen.

Schritt 7: Abmelden

await SocialLogin.logout({ provider: 'oauth2', providerId: 'auth0' });

Das Plugin löscht die gespeicherten Token und öffnet dann logoutUrl mit id_token_hint und post_logout_redirect_uri damit Auth0 das Session-Cookie löscht. Der /oidc/logout Endpoint versteht diese Parameter; das Redirect-Ziel muss in den Allowed Logout URLs eingetragen sein.

Auf iOS und Android öffnet sich die End-Session-Seite im Systembrowser, wodurch der User die App kurzzeitig verlässt. Wenn du nur einen lokalen Logout möchtest, lass logoutUrl und übergeben prompt: 'login' beim nächsten Login, damit eine gespeicherte Auth0-Session den Nutzer nicht sofort wieder automatisch anmeldet. Einstellen von iosPrefersEphemeralSession: true verhindert zudem geteilte Cookies unter iOS, allerdings ohne SSO zwischen den Apps.

Fehlerbehebung

Fehler Ursache Lösung
Callback URL mismatch Redirect-URL nicht in den erlaubten Callback-URLs Kopiere den exakten Wert von code ins Dashboard; prüfe Scheme und Host
Unauthorized oder invalid_client unter /oauth/token App-Typ ist nicht Native oder Auth-Methode ist nicht None Als Native neu erstellen, Token Endpoint Auth auf None setzen
Nein refreshToken im Ergebnis offline_access fehlt oder API erlaubt keinen Offline-Zugriff Scope hinzufügen, Allow Offline Access aktivieren und Rotation einschalten
Access Token kann nicht von API verifiziert werden Nein audience gesendet Füge audience in additionalParameters
App öffnet sich nach Login unter Android nicht erneut Intent-Filter-Scheme oder Host stimmt nicht überein redirectUrl Abgleichen com.example.app und oauth genau
OAuth2 provider "auth0" not configured login aufgerufen vor initialize oder Key-Mismatch Await initialize beim Start dieselbe verwenden providerId
Logout-Seite bleibt offen post_logout_redirect_uri nicht in den Allowed Logout URLs Hinzufügen oder lokalen Logout nutzen
Web CORS-Fehler beim Token-Exchange Origin nicht in Allowed Web Origins Web-Origin hinzufügen oder eine SPA-Anwendung für das Web verwenden

Setzen Sie logsEnabled: true in der Provider-Konfiguration, um die generierten URLs und Details zum Token-Austausch während des Debuggings auszugeben.

Auth-Fixes ohne Store-Release ausrollen

Das Ändern von Scopes, der Audience oder das Error-Handling erfolgt nur in TypeScript. Mit Capgo Live Updates kannst du diese Fixes noch am selben Tag an die User ausrollen. Native Änderungen wie ein neuer Intent Filter erfordern weiterhin ein neues Binary, was Capgo Build in der Cloud erzeugen kann.

Live-Updates für Capacitor-Apps

Wenn ein Bug im Web-Layer live ist, liefere den Fix über Capgo aus, statt Tage auf die App-Store-Freigabe zu warten. Nutzer bekommen das Update im Hintergrund, während native Änderungen im normalen Review-Prozess bleiben.

Neues aus unserem Blog

Capgo gibt dir die besten Insights, um eine wirklich professionelle Mobile App zu erstellen.