Passer au contenu principal

Utiliser l’IA pour intégrer Auth0

Si vous utilisez un assistant de programmation IA comme Claude Code, Cursor ou GitHub Copilot, vous pouvez ajouter automatiquement l’authentification Auth0 en quelques minutes à l’aide des agent skills.Commencez par installer les agent skills Auth0 :
npx skills add auth0/agent-skills --skill auth0-quickstart --skill auth0-ionic-angular
Ensuite, demandez à votre assistant IA :
Add Auth0 authentication to my Ionic Angular app
Votre assistant IA créera automatiquement votre application Auth0, récupérera les identifiants, installera le SDK Angular d’Auth0 et les plugins Capacitor, configurera le deep linking et mettra en place les flux de connexion et de déconnexion avec l’intégration du navigateur natif. Pour en savoir plus, consultez les agent skills Auth0.

Pour commencer

Ce guide de démarrage rapide montre comment ajouter l’authentification Auth0 à une application Ionic Angular avec Capacitor. Vous créerez une application adaptée aux appareils mobiles avec des fonctionnalités de connexion, de déconnexion et de profil utilisateur à l’aide du SDK Auth0 Angular et des plugins de navigateur natifs de Capacitor.
1

Créer un nouveau projet

Créez un projet Ionic Angular avec Capacitor
npx ionic start auth0-ionic-angular tabs --type=angular-standalone --capacitor
Ouvrez le projet
cd auth0-ionic-angular
Assurez-vous d’utiliser le package @ionic/cli (et non le package ionic, maintenant obsolète). Si des erreurs liées à --npm-client s’affichent pendant la création du projet, mettez à jour votre CLI :
npm uninstall -g ionic
npm i -g @ionic/cli
2

Installez le SDK Angular d’Auth0 et les plugins Capacitor

Installez le SDK Angular d’Auth0 ainsi que les plugiciels Browser et App de Capacitor :
npm install @auth0/auth0-angular @capacitor/browser @capacitor/app
Sur iOS, le plugin Browser de Capacitor utilise SFSafariViewController, qui, à partir d’iOS 11, ne partage pas les cookies avec Safari. Cela signifie que l’authentification unique (SSO) ne fonctionnera pas sur ces appareils. Si vous avez besoin du SSO, utilisez un plugin compatible qui s’appuie sur ASWebAuthenticationSession.
3

Configurez votre application Auth0

Ensuite, créez une nouvelle application sur votre locataire Auth0 et ajoutez les variables d’environnement à votre projet.Vous avez trois options pour configurer votre application Auth0 : utiliser l’outil Quick Setup (recommandé), exécuter une commande CLI ou configurer manuellement via le Auth0 Dashboard :
Créez une application native Auth0 et copiez le fichier d’environnement prérempli avec les valeurs de configuration appropriées.Après avoir créé votre application, mettez à jour les Allowed Callback URLs et les Allowed Logout URLs dans l’onglet Settings de l’Auth0 Dashboard. Remplacez YOUR_PACKAGE_ID par la valeur de appId dans votre fichier capacitor.config.ts (par défaut : io.ionic.starter) :Allowed Callback URLs et Allowed Logout URLs :
YOUR_PACKAGE_ID://{yourDomain}/capacitor/YOUR_PACKAGE_ID/callback
4

Configurer le module Auth0

Une fois le fichier d’environnement créé à l’étape précédente, configurez le module Auth0 dans votre application :
src/main.ts
import { bootstrapApplication } from '@angular/platform-browser';
import { RouteReuseStrategy, provideRouter } from '@angular/router';
import { IonicRouteStrategy, provideIonicAngular } from '@ionic/angular/standalone';
import { provideAuth0 } from '@auth0/auth0-angular';
import { environment } from './environments/environment';
import config from '../capacitor.config';
import { routes } from './app/app.routes';
import { AppComponent } from './app/app.component';

const redirect_uri = `${config.appId}://${environment.auth0.domain}/capacitor/${config.appId}/callback`;

bootstrapApplication(AppComponent, {
  providers: [
    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
    provideIonicAngular(),
    provideRouter(routes),
    provideAuth0({
      domain: environment.auth0.domain,
      clientId: environment.auth0.clientId,
      useRefreshTokens: true,
      useRefreshTokensFallback: false,
      authorizationParams: {
        redirect_uri,
      },
    }),
  ],
});
La configuration provideAuth0 comprend :
  • useRefreshTokens: truerequis sur mobile. Les applications Capacitor ne peuvent pas utiliser l’authentification silencieuse basée sur des iframes; des jetons d’actualisation servent donc à renouveler les sessions.
  • useRefreshTokensFallback: falserequis sur mobile. Empêche le SDK de revenir à l’authentification silencieuse basée sur des iframes, qui n’est pas offerte dans les applications natives.
  • authorizationParams.redirect_uri — utilise le schéma d’URL personnalisé de votre application pour y rediriger l’utilisateur après l’authentification.
Pour conserver l’authentification après la fermeture et la réouverture de l’application, il peut être utile de définir cacheLocation à localstorage, mais veuillez prendre connaissance des risques liés au stockage de jetons dans localstorage. De plus, localstorage doit être considéré comme transitoire dans les applications Capacitor. Veuillez consulter les directives sur le stockage dans la documentation Capacitor.
5

Créer des composants Login, Logout et Profile

Créer les fichiers de composants
touch src/app/login-button.component.ts && touch src/app/logout-button.component.ts && touch src/app/profile.component.ts
Ajoutez le code suivant à chaque composant :Mettez maintenant à jour le composant App pour gérer les rappels Auth0 et la page d’accueil pour utiliser vos composants :
Remplacez le contenu de src/app/app.component.ts :
src/app/app.component.ts
import { Component, OnInit, NgZone, inject } from '@angular/core';
import { AuthService } from '@auth0/auth0-angular';
import { mergeMap } from 'rxjs/operators';
import { Browser } from '@capacitor/browser';
import { App } from '@capacitor/app';
import { IonApp, IonRouterOutlet } from '@ionic/angular/standalone';
import { environment } from '../environments/environment';
import config from '../../capacitor.config';

const callbackUri = `${config.appId}://${environment.auth0.domain}/capacitor/${config.appId}/callback`;

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [IonApp, IonRouterOutlet],
  template: '<ion-app><ion-router-outlet></ion-router-outlet></ion-app>',
})
export class AppComponent implements OnInit {
  private auth = inject(AuthService);
  private ngZone = inject(NgZone);

  ngOnInit(): void {
    App.addListener('appUrlOpen', ({ url }) => {
      this.ngZone.run(() => {
        if (url?.startsWith(callbackUri)) {
          if (
            url.includes('state=') &&
            (url.includes('error=') || url.includes('code='))
          ) {
            this.auth
              .handleRedirectCallback(url)
              .pipe(mergeMap(() => Browser.close()))
              .subscribe();
          } else {
            Browser.close();
          }
        }
      });
    });
  }
}
La fonction de rappel de l’événement appUrlOpen dans le composant App est enveloppée dans this.ngZone.run(). Cela est obligatoire, car les fonctions de rappel des plugiciels Capacitor s’exécutent en dehors de la zone d’Angular et, sans cela, Angular ne détectera pas les changements d’état d’authentification après la connexion. Consultez Using Angular with Capacitor pour en savoir plus.
6

Lancez votre application

Testez d’abord dans le navigateur :
ionic serve
Lorsque vous exécutez l’application dans le navigateur avec ionic serve, la redirection avec un schéma d’URL personnalisé ne fonctionne pas, car les navigateurs ne peuvent pas gérer les schémas d’URL personnalisés. Pour effectuer des tests dans le navigateur, remplacez temporairement redirect_uri par http://localhost:8100 dans src/main.ts, puis ajoutez http://localhost:8100 aux champs Allowed Callback URLs et Allowed Logout URLs de votre application Auth0 dans l’Auth0 Dashboard. N’oubliez pas de rétablir cette valeur avant de générer la version native.
Pour exécuter l’application sur un appareil ou un simulateur, ajoutez d’abord les plateformes natives :
npx cap add ios
npx cap add android
Ensuite, générez, synchronisez et exécutez :
ionic build && npx cap sync && npx cap run ios
Vous devez ajouter les plateformes natives avec npx cap add avant de pouvoir exécuter l’application sur celles-ci. Cette opération n’est requise qu’une seule fois par plateforme. Assurez-vous que votre schéma URL personnalisé est enregistré (voir Utilisation avancée ci-dessous).
Point de contrôleVous devriez maintenant avoir une page de connexion Auth0 entièrement fonctionnelle sur votre localhost

Utilisation avancée

Si vous avez créé votre projet avec --type=angular (au lieu de --type=angular-standalone) ou si vous préférez utiliser des NgModules, configurez le SDK avec AuthModule.forRoot :
src/app/app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouteReuseStrategy } from '@angular/router';
import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
import { AuthModule } from '@auth0/auth0-angular';
import { environment } from '../environments/environment';
import config from '../../capacitor.config';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

const redirect_uri = `${config.appId}://${environment.auth0.domain}/capacitor/${config.appId}/callback`;

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    IonicModule.forRoot(),
    AppRoutingModule,
    AuthModule.forRoot({
      domain: environment.auth0.domain,
      clientId: environment.auth0.clientId,
      useRefreshTokens: true,
      useRefreshTokensFallback: false,
      authorizationParams: {
        redirect_uri,
      },
    }),
  ],
  providers: [{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy }],
  bootstrap: [AppComponent],
})
export class AppModule {}
Lorsque vous utilisez des NgModules, injectez AuthService dans le constructeur (constructor(public auth: AuthService)) plutôt qu’avec inject(). Utilisez *ngIf="auth.user$ | async as user" dans les modèles au lieu de la syntaxe de contrôle de flux @if. Les composants doivent être déclarés dans le module plutôt que définis avec standalone: true.
Pour tester l’authentification sur un appareil réel, enregistrez votre schéma d’URL personnalisé pour chaque plateforme.

iOS

Enregistrez votre schéma d’URL personnalisé dans ios/App/App/Info.plist :
<key>CFBundleURLTypes</key>
<array>
  <dict>
    <key>CFBundleURLSchemes</key>
    <array>
      <string>YOUR_PACKAGE_ID</string>
    </array>
  </dict>
</array>
Remplacez YOUR_PACKAGE_ID par votre appId dans capacitor.config.ts. Pour en savoir plus, consultez Defining a Custom URL Scheme.

Android

Ajoutez un filtre d’intention à android/app/src/main/AndroidManifest.xml, à l’intérieur de la balise <activity> :
<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="YOUR_PACKAGE_ID" />
</intent-filter>
Remplacez YOUR_PACKAGE_ID par votre appId dans capacitor.config.ts. Pour en savoir plus, consultez Create Deep Links to App Content.

Compiler et exécuter sur un appareil

ionic build && npx cap sync && npx cap open ios
Ou pour Android :
ionic build && npx cap sync && npx cap open android
Utilisez le guard fonctionnel pour protéger les routes qui nécessitent une authentification :
src/app/app.routes.ts
import { Routes } from '@angular/router';
import { authGuardFn } from '@auth0/auth0-angular';

export const routes: Routes = [
  {
    path: 'tabs',
    loadComponent: () => import('./tabs/tabs.page').then((m) => m.TabsPage),
    children: [
      {
        path: 'tab1',
        loadComponent: () => import('./tab1/tab1.page').then((m) => m.Tab1Page),
      },
      {
        path: 'tab2',
        loadComponent: () => import('./tab2/tab2.page').then((m) => m.Tab2Page),
        canActivate: [authGuardFn],
      },
      {
        path: 'tab3',
        loadComponent: () => import('./tab3/tab3.page').then((m) => m.Tab3Page),
        canActivate: [authGuardFn],
      },
      {
        path: '',
        redirectTo: '/tabs/tab1',
        pathMatch: 'full',
      },
    ],
  },
  {
    path: '',
    redirectTo: '/tabs/tab1',
    pathMatch: 'full',
  },
];
Lorsqu’un utilisateur non authentifié accède à une route protégée, authGuardFn le redirige automatiquement vers la page de connexion Auth0.
Configurez l’intercepteur HTTP pour ajouter automatiquement des jetons d’accès aux appels d’API :
src/main.ts
import { bootstrapApplication } from '@angular/platform-browser';
import { RouteReuseStrategy, provideRouter } from '@angular/router';
import { IonicRouteStrategy, provideIonicAngular } from '@ionic/angular/standalone';
import { provideHttpClient, withInterceptors } from '@angular/common/http';
import { provideAuth0, authHttpInterceptorFn } from '@auth0/auth0-angular';
import { environment } from './environments/environment';
import config from '../capacitor.config';
import { routes } from './app/app.routes';
import { AppComponent } from './app/app.component';

const redirect_uri = `${config.appId}://${environment.auth0.domain}/capacitor/${config.appId}/callback`;

bootstrapApplication(AppComponent, {
  providers: [
    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
    provideIonicAngular(),
    provideRouter(routes),
    provideAuth0({
      domain: environment.auth0.domain,
      clientId: environment.auth0.clientId,
      useRefreshTokens: true,
      useRefreshTokensFallback: false,
      authorizationParams: {
        redirect_uri,
        audience: 'YOUR_API_IDENTIFIER',
      },
      httpInterceptor: {
        allowedList: [
          'http://localhost:3001/api/*',
        ],
      },
    }),
    provideHttpClient(
      withInterceptors([authHttpInterceptorFn])
    ),
  ],
});
Ensuite, effectuez des appels d’API à l’aide de HttpClient d’Angular : l’intercepteur ajoute automatiquement le jeton Bearer :
src/app/api.service.ts
import { Injectable, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({ providedIn: 'root' })
export class ApiService {
  private http = inject(HttpClient);

  getData() {
    return this.http.get('http://localhost:3001/api/data');
  }
}
httpInterceptor.allowedList détermine quels points de terminaison d’API reçoivent des jetons d’accès. Incluez le paramètre audience pour demander un jeton d’accès pour votre API. Remplacez YOUR_API_IDENTIFIER par l’identifiant indiqué dans Auth0 Dashboard > APIs.

Erreur de non-correspondance de l’URL de rappel

Solution : Vérifiez que l’URL de rappel dans votre Auth0 Dashboard correspond exactement à l’URL construite dans votre application. Assurez-vous que YOUR_PACKAGE_ID correspond au champ appId dans votre fichier capacitor.config.ts.

L’écran ne se met pas à jour après la connexion

Solution : Assurez-vous que la fonction de rappel de l’événement appUrlOpen est encapsulée dans this.ngZone.run(). Sinon, Angular ne détectera pas les changements d’état provenant de handleRedirectCallback. Consultez Using Angular with Capacitor.

Erreur « PKCE not allowed »

Correctif :
  1. Accédez à Auth0 Dashboard > Applications > Your Application
  2. Définissez Application Type sur Native
  3. Définissez Token Endpoint Authentication Method sur None
  4. Enregistrez les modifications et réessayez

Le SSO ne fonctionne pas sur iOS

Le plugin Browser de Capacitor utilise SFSafariViewController, qui ne partage pas les témoins avec Safari sur iOS 11+. Si vous avez besoin du SSO, utilisez un plugin compatible qui utilise ASWebAuthenticationSession.

La connexion fonctionne, mais l’utilisateur reste non authentifié après le redémarrage de l’application

Activez cacheLocation: 'localstorage' dans la configuration provideAuth0 pour conserver les jetons d’une session à l’autre après le redémarrage de l’application. Tenez compte des implications de sécurité et des limitations de stockage de Capacitor.

L’observable ne s’exécute jamais

Toutes les méthodes AuthService renvoient des observables froids. Vous devez appeler .subscribe() pour qu’elles s’exécutent. Si loginWithRedirect() ou logout() semble ne rien faire, vérifiez que .subscribe() est bien chaîné à la fin.

Étapes suivantes

Consultez les ressources suivantes pour en savoir plus :