Per effettuare il login con Auth0 in un'app Capacitor, crea una Nativo application in Auth0, registra un URL di callback con custom-scheme come com.example.app://oauth/auth0, ed esegui il flusso di autorizzazione OpenID Connect code con PKCE tramite il browser di sistema. Con @capgo/capacitor-social-login quello è un initialize chiamata con i tuoi endpoint Auth0 e un SocialLogin.login({ provider: 'oauth2', options: { providerId: 'auth0' } }).
Questa guida copre le impostazioni della dashboard di Auth0, il client code per iOS, Android e web, gli API access token, i refresh token, il logout e gli errori che potresti incontrare. È aggiornata alla versione Capacitor 8 di ottobre 2026.
Come funziona il flusso Auth0 in Capacitor
Auth0 ospita la pagina di login (Universal Login). La tua app non vedrà mai la password. Il flusso è:
- L'app genera un PKCE verifier e un challenge, quindi apre
https://YOUR_TENANT/authorizeun browser sicuro. - L'utente effettua il login (password, social, passkey, MFA, o qualunque cosa tu abbia configurato in Auth0).
- Auth0 reindirizza alla tua callback URL con un codice monouso
code. - L'app scambia il code e il PKCE verifier presso
/oauth/tokenper un ID token, un access token e, opzionalmente, un refresh token.
Il browser utilizzato dipende dalla piattaforma:
| Piattaforma | Browser | Gestione callback |
|---|---|---|
| iOS | ASWebAuthenticationSession |
Gestita dal sistema, nessuna Info.plist modifica |
| Android | WebView integrata di default, o Chrome Custom Tabs con androidUseCustomTabs: true |
Custom Tabs richiedono un intent filter |
| Web | Popup (default) o redirect a pagina intera | handleRedirectCallback() sulla pagina di ritorno |
Su Android, usa Custom Tabs. Condividono i cookie con Chrome, supportano passkey e password manager e seguono lo standard RFC 8252 (OAuth per app native), come richiesto da Auth0.
Passaggio 1: Configura l'applicazione Auth0
- Nel Dashboard di Auth0, vai su Applications > Applications > Create Application.
- Scegli Nativo e crearlo.
- Sul Impostazioni tab, nota il Domain (ad esempio
example.eu.auth0.com) e il ID Client. - Sotto Credenziali, verifica che il metodo di autenticazione sia Nessuna. Si tratta dell'impostazione public-client usata con PKCE.
URL di callback e logout
Compila questi campi Impostazioni > Application URIs:
| Campo | Valore per mobile | Valore per web |
|---|---|---|
| URL di callback consentiti | com.example.app://oauth/auth0 |
https://app.example.com/auth/callback |
| URL di logout consentiti | com.example.app://oauth/logout |
https://app.example.com/ |
| Origini web consentite | Non necessario | https://app.example.com |
Separa i valori con la virgola. Usa il tuo Capacitor appId come schema. Uno schema reverse-domain evita collisioni con altre app. Se pubblichi anche una build web, molti team creano una Single Page Application in Auth0, così le impostazioni web e mobile non si sovrappongono.
Refresh token
Se gli utenti devono rimanere autenticati:
- In Impostazioni > Refresh Token Rotation, attiva la rotazione. Ogni refresh restituisce un nuovo refresh token e invalida il precedente.
- Imposta una durata assoluta e di inattività adatta al tuo prodotto.
- Se chiami il tuo API, apri Applications > APIs > il tuo API > Settings e abilita Consenti l'accesso offline.
- Richiedi lo
offline_accessscope nell'app.
audience di API
Se il tuo backend valida i token di accesso Auth0, crea un API in Applicazioni > API con un identificatore come https://api.example.com. Passa quell'identificatore come audience. Senza di esso, l'access token è valido solo per l'Auth0 /userinfo endpoint.
Passaggio 2: Installa e configura il plugin
bun add @capgo/capacitor-social-login
bunx cap sync
Se Auth0 è il tuo unico provider, disabilita gli SDK social inclusi per mantenere il binario leggero:
// capacitor.config.ts
plugins: {
SocialLogin: {
providers: { google: false, facebook: false, apple: false, twitter: false },
},
},
Il motore OAuth2 generico non dipende da quegli SDK.
Android intent filter per Custom Tabs
Aggiungi lo scheme di callback a MainActivity nella 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>
Il template Capacitor imposta già android:launchMode="singleTask" su MainActivity, necessario per il redirect. Mantienilo.
Passaggio 3: Inizializza il provider Auth0
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,
},
},
});
}
Puoi sostituire gli endpoint espliciti con issuerUrl: AUTH0_DOMAIN. Il plugin legge quindi /.well-known/openid-configuration. I valori espliciti prevalgono su quelli rilevati, utile se usi un dominio custom Auth0.
Se stai passando da Ionic Auth Connect, il plugin esporta anche SocialLoginAuthConnect con un auth0 preset che accetta domain, clientId, redirectUrl e audience. Vedi la Guida alla migrazione da Auth Connect.
Passaggio 4: Effettua il login
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;
}
}
Opzioni di login utili:
prompt: 'login'forza la pagina di login anche se Auth0 ha ancora un cookie di sessione attivo.loginHint: 'user@example.com'precompila l'email.additionalParameters: { connection: 'google-oauth2' }salta l'Universal Login e passa direttamente a una connessione.additionalParameters: { screen_hint: 'signup' }apre la schermata di registrazione.
Callback di redirect web
Sul web, il flusso popup predefinito non richiede nulla di extra. Se usi flow: 'redirect', leggi il risultato sulla callback page:
const result = await SocialLogin.handleRedirectCallback();
if (result?.provider === 'oauth2') {
console.log(result.result.idToken);
}
handleRedirectCallback is web only and rejects on iOS and Android.
Passaggio 5: Leggi l'ID token e chiama il tuo API
Decodifica l'ID token sul client solo per la visualizzazione:
const { claims } = await SocialLogin.decodeIdToken({ idToken: result.idToken! });
console.log(claims.email, claims.name, claims.sub);
decodeIdToken non controlla la firma. Per qualsiasi aspetto relativo alla sicurezza, invia l'access token al tuo API e validalo lì:
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
}
Passaggio 6: Refresh dell'access token
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 rifiuta quando il refresh token è scaduto o revocato. Con la rotazione attiva, fallisce anche un refresh token già utilizzato, quindi gestisci sempre il rifiuto reindirizzando l'utente al login.
refresh usa il refresh token salvato dal plugin al login. Se gestisci tu il refresh token, chiama SocialLogin.refreshToken({ provider: 'oauth2', providerId: 'auth0', refreshToken }), che restituisce la risposta completa con il nuovo token. Con la rotazione attiva, salva il nuovo refresh token ogni volta.
Il plugin mantiene una copia del token nello storage privato dell'app. Se la tua revisione di sicurezza richiede Keychain o Keystore, salva il refresh token con NativeBiometric.setData({ key, value }) da @capgo/capacitor-native-biometric e passalo a refreshToken te stesso. Il nostro guida allo storage sicuro dei token confronta le opzioni.
Passaggio 7: Logout
await SocialLogin.logout({ provider: 'oauth2', providerId: 'auth0' });
Il plugin elimina i token salvati e poi apre logoutUrl con id_token_hint e post_logout_redirect_uri quindi Auth0 cancella il suo cookie di sessione. Auth0's /oidc/logout riconosce quei parametri e il target del redirect deve essere elencato in URL di logout consentiti.
Su iOS e Android la pagina di end-session si apre nel browser di sistema, quindi l'utente esce brevemente dall'app. Se vuoi solo un logout locale, ometti logoutUrl e passa prompt: 'login' al prossimo login, in modo che una sessione Auth0 memorizzata non riacceda l'utente automaticamente. Impostazione iosPrefersEphemeralSession: true evita anche la condivisione dei cookie su iOS, rinunciando però al SSO tra le app.
Risoluzione problemi
| Errore | Causa | Soluzione |
|---|---|---|
Callback URL mismatch |
URL di redirect non presente negli Allowed Callback URLs | Copia il valore esatto da code nella dashboard, controlla lo scheme e l'host |
Unauthorized o invalid_client a /oauth/token |
Il tipo di app non è Native o il metodo di auth non è None | Imposta come Native e imposta token endpoint auth su None |
No refreshToken nel risultato |
offline_access mancante o API non permette l'accesso offline |
Aggiungi lo scope, abilita Allow Offline Access e abilita la rotation |
| L'access token non può essere verificato da API | No audience inviato |
Aggiungi audience nella additionalParameters |
| L'app non si riapre dopo il login su Android | Lo scheme o l'host dell'intent filter non corrispondono redirectUrl |
Abbina com.example.app e oauth esattamente |
OAuth2 provider "auth0" not configured |
login chiamato prima di initialize o mismatch della chiave |
Await initialize all'avvio, usa lo stesso providerId |
| La pagina di logout resta aperta | post_logout_redirect_uri non presente negli Allowed Logout URLs |
Aggiungilo, o usa il logout locale |
| Errore CORS web durante lo scambio del token | Origin non presente negli Allowed Web Origins | Aggiungi l'origin web, o usa una SPA per il web |
Imposta logsEnabled: true nella configurazione del provider per stampare gli URL generati e i dettagli dello scambio del token durante il debug.
Rilascia fix di auth senza passare dagli store
Modificare gli scope, l'audience o la gestione degli errori è possibile solo in TypeScript. Con Live updates di Capgo puoi distribuire i fix agli utenti lo stesso giorno. Le modifiche native, come un nuovo intent filter, richiedono ancora un nuovo binario, che Build Capgo può essere generato nel cloud.