> ## Documentation Index
> Fetch the complete documentation index at: https://translations.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Ajouter la connexion à votre application Angular

> Ce guide explique comment intégrer Auth0, ajouter l’authentification et afficher les renseignements du profil utilisateur dans toute application Angular à l’aide du SDK Auth0 Angular.

export const HowToSchema = () => <script type="application/ld+json">
    {'{"@context":"https://schema.org","@type":"HowTo"}'}
  </script>;

export const CreateInteractiveApp = ({placeholderText = "Auth0", appType = "regular_web", allowedCallbackUrls = ["localhost:3000"], allowedLogoutUrls = ["localhost:3000"], allowedOriginUrls = ["localhost:3000"]}) => {
  const [isAuthenticated, setIsAuthenticated] = useState(false);
  const [storeReady, setStoreReady] = useState(false);
  const [displayForm, setDisplayForm] = useState(true);
  useEffect(() => {
    const init = () => setStoreReady(true);
    if (window.rootStore) {
      window.rootStore.clientStore.setSelectedClient(null);
      window.rootStore.clientStore.setSelectedClientSecret(undefined);
      init();
    } else {
      window.addEventListener("adu:storeReady", init);
    }
    return () => {
      window.removeEventListener("adu:storeReady", init);
    };
  }, []);
  useEffect(() => {
    if (!storeReady) return;
    const disposer = autorun(() => {
      const rootStore = window.rootStore;
      setIsAuthenticated(rootStore.sessionStore.isAuthenticated);
    });
    return () => {
      disposer();
    };
  }, [storeReady]);
  if (!storeReady || typeof window === "undefined" || !displayForm) {
    return <></>;
  }
  const login = () => {
    const baseUrl = window.rootStore.config.apiBaseUrl;
    const returnTo = encodeURIComponent(window.location.href);
    window.location.href = `${baseUrl}/auth/user/login?returnTo=${returnTo}`;
  };
  const Card = ({className = "", children}) => {
    return <div className={`
          flex border rounded-2xl
          border-gray-950/10 dark:border-white/10
          py-3.5 px-4 gap-2
          text-sm text-gray-900 dark:text-gray-200
          ${className}
        `}>
        {children}
      </div>;
  };
  const Button = ({children, ...props}) => {
    return <button className="bg-[--button-primary] text-[--foreground-inverse] px-[1.125rem] py-1.5 rounded-lg font-medium" {...props}>
        {children}
      </button>;
  };
  const CreateApplicationForm = () => {
    const [name, setName] = useState("");
    const [isLoading, setIsLoading] = useState(false);
    const [error, setError] = useState("");
    const handleSubmit = async () => {
      if (!name.trim()) {
        setError("Le nom de l'application est obligatoire");
        return;
      }
      setIsLoading(true);
      setError(null);
      try {
        await window.rootStore.clientStore.createClient({
          name: name.trim(),
          app_type: appType,
          callbacks: allowedCallbackUrls,
          allowed_logout_urls: allowedLogoutUrls,
          web_origins: allowedOriginUrls,
          client_metadata: {
            created_by: "quickstart-docs-app-creation-component"
          }
        });
        setDisplayForm(false);
      } catch (err) {
        console.error("Erreur lors de la création du client :", err);
        const errorMessage = err instanceof Error ? err.message : "Échec de la création de l'application";
        setError(errorMessage);
      } finally {
        setIsLoading(false);
      }
    };
    return <Card className="flex-col items-start p-4 gap-3.75">
        <span className="font-medium text-gray-900 dark:text-gray-200">Créer une Auth0 App</span>
        <div className="w-full flex gap-2">
          <input id="app-name" name={name} className="
              w-full max-w-[448px] h-11 py-2 px-4 
              border rounded-lg border-gray-950/10 dark:border-white/10 
              text-gray-900 dark:text-gray-200
              focus:outline-none dark:focus:outline-none
            " placeholder={`Mon application ${placeholderText}`} value={name} onChange={e => setName(e.target.value)} />
          <Button onClick={handleSubmit}>{isLoading ? "Création en cours..." : "Créer"}</Button>
        </div>
        {error && <p className="text-red-500">{error}</p>}
      </Card>;
  };
  const SignInForm = () => {
    return <Card className="items-center">
        <Button onClick={login}>Se connecter</Button> <span>pour créer l'application</span>
      </Card>;
  };
  return isAuthenticated ? <CreateApplicationForm /> : <SignInForm />;
};

export const AuthCodeBlock = ({filename, icon, language, highlight, children}) => {
  const [displayText, setDisplayText] = useState(children);
  const [copyText, setCopyText] = useState(children);
  const wrapperRef = React.useRef(null);
  useEffect(() => {
    let unsubscribe = null;
    function init() {
      if (!window.autorun || !window.rootStore) {
        return;
      }
      unsubscribe = window.autorun(() => {
        let processedChildrenForDisplay = children;
        let processedChildrenForCopy = children;
        for (const [key, value] of window.rootStore.variableStore.values.entries()) {
          const escapedKey = key.replaceAll(/[.*+?^${}()|[\]\\]/g, (String.raw)`\$&`);
          let displayValue = value;
          if (key === "{yourClientSecret}" && value !== "{yourClientSecret}") {
            displayValue = value.substring(0, 3) + "*****MASQUÉ*****";
          }
          processedChildrenForDisplay = processedChildrenForDisplay.replaceAll(new RegExp(escapedKey, "g"), displayValue);
          processedChildrenForCopy = processedChildrenForCopy.replaceAll(new RegExp(escapedKey, "g"), value);
        }
        setDisplayText(processedChildrenForDisplay);
        setCopyText(processedChildrenForCopy);
      });
    }
    if (window.rootStore) {
      init();
    } else {
      window.addEventListener("adu:storeReady", init);
    }
    return () => {
      window.removeEventListener("adu:storeReady", init);
      unsubscribe?.();
    };
  }, [children]);
  useEffect(() => {
    if (!wrapperRef.current) return;
    const originalWriteText = navigator.clipboard.writeText.bind(navigator.clipboard);
    let isOverriding = false;
    const handleClick = e => {
      const button = e.target.closest('[data-testid="copy-code-button"]');
      if (!button || !wrapperRef.current.contains(button)) return;
      isOverriding = true;
      navigator.clipboard.writeText = text => {
        if (isOverriding) {
          isOverriding = false;
          navigator.clipboard.writeText = originalWriteText;
          return originalWriteText(copyText);
        }
        return originalWriteText(text);
      };
      setTimeout(() => {
        if (isOverriding) {
          isOverriding = false;
          navigator.clipboard.writeText = originalWriteText;
        }
      }, 100);
    };
    const wrapper = wrapperRef.current;
    wrapper.addEventListener('click', handleClick, true);
    return () => {
      wrapper.removeEventListener('click', handleClick, true);
      if (navigator.clipboard.writeText !== originalWriteText) {
        navigator.clipboard.writeText = originalWriteText;
      }
    };
  }, [copyText]);
  return <div ref={wrapperRef}>
      <CodeBlock filename={filename} icon={icon} language={language} lines highlight={highlight}>
        {displayText}
      </CodeBlock>
    </div>;
};

export const AuthCodeGroup = ({children, dropdown}) => {
  const [processedChildren, setProcessedChildren] = useState(children);
  useEffect(() => {
    let unsubscribe = null;
    function init() {
      unsubscribe = window.autorun(() => {
        const processChildren = node => {
          if (typeof node === "string") {
            let processedNode = node;
            for (const [key, value] of window.rootStore.variableStore.values.entries()) {
              const escapedKey = key.replaceAll(/[.*+?^${}()|[\]\\]/g, (String.raw)`\$&`);
              processedNode = processedNode.replaceAll(new RegExp(escapedKey, "g"), value);
            }
            return processedNode;
          } else if (Array.isArray(node)) {
            return node.map(processChildren);
          } else if (node && node.props && node.props.children) {
            return {
              ...node,
              props: {
                ...node.props,
                children: processChildren(node.props.children)
              }
            };
          }
          return node;
        };
        setProcessedChildren(processChildren(children));
      });
    }
    if (window.rootStore) {
      init();
    } else {
      window.addEventListener("adu:storeReady", init);
    }
    return () => {
      window.removeEventListener("adu:storeReady", init);
      unsubscribe?.();
    };
  }, [children]);
  return <CodeGroup dropdown={dropdown}>{processedChildren}</CodeGroup>;
};

<HowToSchema />

<Accordion title="Utiliser l’IA pour intégrer Auth0" icon="microchip-ai" iconType="solid" defaultOpen>
  Si vous utilisez un assistant IA de programmation comme Claude Code, Cursor ou GitHub Copilot, vous pouvez ajouter automatiquement l’authentification Auth0 en quelques minutes à l’aide d’[Agent Skills](https://agentskills.io/home).

  **Installer :**

  ```bash theme={null}
  npx skills add auth0/agent-skills --skill auth0
  ```

  **Ensuite, demandez à votre assistant IA :**

  ```text theme={null}
  Add Auth0 authentication to my Angular app
  ```

  Votre assistant IA créera automatiquement votre application Auth0, récupérera les identifiants, installera `@auth0/auth0-angular`, créera des gardes de route et des intercepteurs HTTP, puis configurera votre environnement. [Documentation complète sur Agent Skills →](/docs/fr-ca/quickstart/agent-skills)
</Accordion>

<Note>
  **Prérequis :** Avant de commencer, assurez-vous d’avoir installé les éléments suivants :

  * **[Node.js](https://nodejs.org/en/download)** 20 LTS ou une version plus récente
  * **[npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)** 10+ ou **[yarn](https://classic.yarnpkg.com/lang/en/docs/install/)** 1.22+ ou **[pnpm](https://pnpm.io/installation)** 8+
  * **[jq](https://jqlang.org/)** - Requis pour configurer Auth0 CLI

  Vérifiez l’installation : `node --version && npm --version`

  **Compatibilité des versions d’Angular :** Ce Quickstart fonctionne avec **Angular 19 à 21** à l’aide d’Angular CLI. Le SDK `@auth0/auth0-angular` prend en charge Angular 13 et les versions plus récentes.
</Note>

<div id="get-started">
  ## Pour commencer
</div>

Ce guide de démarrage rapide explique comment ajouter l’authentification Auth0 à une application Angular. Vous créerez une application monopage sécurisée avec des fonctionnalités de connexion et de déconnexion à l’aide du système d’injection de dépendances d’Angular et du SDK Auth0 Angular.

export const localEnvSnippet = `export const environment = {
  production: false,
  auth0: {
    domain: {yourDomain},
    clientId: {yourClientId}
  }
};`;

<Steps>
  <Step title="Créer un nouveau projet" stepNumber={1}>
    Créez un nouveau projet Angular pour ce Quickstart

    ```shellscript theme={null}
    npx @angular/cli@latest new auth0-angular --routing=true --style=css
    ```

    Ouvrir le projet

    ```shellscript theme={null}
    cd auth0-angular
    ```
  </Step>

  <Step title="Installer le SDK Auth0 Angular" stepNumber={2}>
    ```shellscript theme={null}
    npm install @auth0/auth0-angular && npm install
    ```
  </Step>

  <Step title="Configurez votre Auth0 App" stepNumber={3}>
    Ensuite, vous devez créer une nouvelle application sur votre tenant Auth0 et ajouter 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 Dashboard :

    <Tabs>
      <Tab title="Configuration rapide (recommandée)">
        Créez une Auth0 App, puis copiez le fichier `.env` prérempli avec les valeurs de configuration appropriées.

        <CreateInteractiveApp placeholderText="Angular" appType="spa" allowedCallbackUrls={["http://localhost:4200"]} allowedLogoutUrls={["http://localhost:4200"]} allowedOriginUrls={["http://localhost:4200"]} />

        <AuthCodeBlock children={localEnvSnippet} language="typescript" filename="src/environments/environment.ts" />
      </Tab>

      <Tab title="CLI">
        Exécutez la commande shell suivante dans le répertoire racine de votre projet pour créer une application Auth0 et générer un fichier d’environnement :

        <CodeGroup>
          ```shellscript Mac theme={null}
          # Installer Auth0 CLI (s’il n’est pas déjà installé)
          brew tap auth0/auth0-cli && brew install auth0

          # Configurer l’application Auth0 et générer le fichier d’environnement
          auth0 qs setup --app --type spa --framework angular --name "My Angular App" --port 4200
          ```

          ```powershell Windows theme={null}
          # Installer Auth0 CLI (s’il n’est pas déjà installé)
          scoop bucket add auth0 https://github.com/auth0/scoop-auth0-cli.git
          scoop install auth0

          # Configurer l’application Auth0 et générer le fichier d’environnement
          auth0 qs setup --app --type spa --framework angular --name "My Angular App" --port 4200
          ```
        </CodeGroup>

        <Note>
          Cette commande va :

          1. Vérifier si vous êtes authentifié (et vous inviter à vous connecter au besoin)
          2. Créer une application Auth0 Single Page Application configurée pour `http://localhost:4200`
          3. Générer `src/environments/environment.ts` avec votre domaine Auth0 et votre ID client
        </Note>
      </Tab>

      <Tab title="Dashboard">
        Avant de commencer, créez un fichier d’environnement dans votre projet

        ```typescript src/environments/environment.ts theme={null}
        export const environment = {
          production: false,
          auth0: {
            domain: 'YOUR_AUTH0_APP_DOMAIN',
            clientId: 'YOUR_AUTH0_APP_CLIENT_ID'
          }
        };
        ```

        1. Accédez au [Auth0 Dashboard](https://manage.auth0.com/dashboard/)
        2. Cliquez sur **Applications** > **Applications** > **Create Application**
        3. Dans la fenêtre contextuelle, saisissez un nom pour votre application, sélectionnez `Single Page Web Application` comme type d’application, puis cliquez sur **Create**
        4. Allez à l’onglet **Settings** de la page Application Details
        5. Remplacez `YOUR_AUTH0_APP_DOMAIN` et `YOUR_AUTH0_APP_CLIENT_ID` dans le fichier `src/environments/environment.ts` par les valeurs **Domain** et **Client ID** du Dashboard

        Enfin, dans l’onglet **Settings** de la page Application Details, configurez les URL suivantes :

        **Allowed Callback URLs:**

        ```
        http://localhost:4200
        ```

        **URL de déconnexion autorisées :**

        ```
        http://localhost:4200
        ```

        **Origines Web autorisées :**

        ```
        http://localhost:4200
        ```

        <Info>
          Les **Allowed Callback URLs** constituent une mesure de sécurité essentielle pour garantir que les utilisateurs sont redirigés de façon sécuritaire vers votre application après l’authentification. Sans URL correspondante, le processus de connexion échouera et les utilisateurs verront une page d’erreur Auth0 au lieu d’accéder à votre application.

          Les **Allowed Logout URLs** sont essentielles pour offrir une expérience utilisateur fluide au moment de la déconnexion. Sans URL correspondante, les utilisateurs ne seront pas redirigés vers votre application après la déconnexion et resteront plutôt sur une page Auth0 générique.

          **Allowed Web Origins** est essentiel pour l’authentification silencieuse. Sans cela, les utilisateurs seront déconnectés lorsqu’ils actualisent la page ou reviennent plus tard dans votre application.
        </Info>
      </Tab>
    </Tabs>
  </Step>

  <Step title="Configurer le module Auth0" stepNumber={4}>
    Une fois le fichier d’environnement de l’étape précédente en place, ajoutez `provideAuth0` au tableau `providers` de votre `app.config.ts` :

    ```typescript src/app/app.config.ts {3,4,5,11-17} lines theme={null}
    import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
    import { provideRouter } from '@angular/router';
    import { provideAuth0 } from '@auth0/auth0-angular';
    import { environment } from '../environments/environment';
    import { routes } from './app.routes';

    export const appConfig: ApplicationConfig = {
      providers: [
        provideZoneChangeDetection({ eventCoalescing: true }),
        provideRouter(routes),
        provideAuth0({
          domain: environment.auth0.domain,
          clientId: environment.auth0.clientId,
          authorizationParams: {
            redirect_uri: window.location.origin
          }
        })
      ]
    };
    ```

    <Note>
      Si vous configurez manuellement votre application Auth0 dans le dashboard, créez `src/environments/environment.ts` avec votre domaine et votre ID client du dashboard.

      Les projets Angular 20+ incluent aussi `provideBrowserGlobalErrorListeners()` dans ce fichier — laissez-le dans le tableau aux côtés de `provideAuth0`. Aucune modification à `main.ts` n’est nécessaire.
    </Note>
  </Step>

  <Step title="Créer les composants Login, Logout et Profil" stepNumber={5}>
    Utilisez l'Angular CLI pour générer les fichiers du composant :

    ```shellscript theme={null}
    ng generate component components/login-button --inline-template --inline-style --skip-tests && \
    ng generate component components/logout-button --inline-template --inline-style --skip-tests && \
    ng generate component components/profile --inline-template --inline-style --skip-tests
    ```

    Ajoutez le code suivant à chaque composant :

    <AuthCodeGroup>
      ```typescript src/app/components/login-button.component.ts expandable lines theme={null}
      import { Component, inject } from '@angular/core';
      import { AuthService } from '@auth0/auth0-angular';

      @Component({
        selector: 'app-login-button',
        standalone: true,
        template: `
          <button 
            (click)="loginWithRedirect()" 
            class="button login"
          >
            Log In
          </button>
        `
      })
      export class LoginButtonComponent {
        private auth = inject(AuthService);

        loginWithRedirect(): void {
          this.auth.loginWithRedirect();
        }
      }
      ```

      ```typescript src/app/components/logout-button.component.ts expandable lines theme={null}
      import { Component, inject } from '@angular/core';
      import { AuthService } from '@auth0/auth0-angular';

      @Component({
        selector: 'app-logout-button',
        standalone: true,
        template: `
          <button
            (click)="logout()"
            class="button logout"
          >
            Log Out
          </button>
        `
      })
      export class LogoutButtonComponent {
        private auth = inject(AuthService);

        logout(): void {
          this.auth.logout({ 
            logoutParams: { 
              returnTo: window.location.origin 
            } 
          });
        }
      }
      ```

      ```typescript src/app/components/profile.component.ts expandable lines theme={null}
      import { Component, inject } from '@angular/core';
      import { AuthService } from '@auth0/auth0-angular';
      import { CommonModule } from '@angular/common';

      @Component({
        selector: 'app-profile',
        standalone: true,
        imports: [CommonModule],
        template: `
          @if (auth.isLoading$ | async) {
            <div class="loading-text">Loading profile...</div>
          }
          
          @if ((auth.isAuthenticated$ | async) && (auth.user$ | async); as user) {
            <div style="display: flex; flex-direction: column; align-items: center; gap: 1rem;">
              @if (user.picture) {
                <img 
                  [src]="user.picture" 
                  [alt]="user.name || 'User'"
                  class="profile-picture"
                  style="
                    width: 110px; 
                    height: 110px; 
                    border-radius: 50%; 
                    object-fit: cover;
                    border: 3px solid #63b3ed;
                  "
                />
              }
              <div style="text-align: center;">
                <div 
                  class="profile-name" 
                  style="
                    font-size: 2rem; 
                    font-weight: 600; 
                    color: #f7fafc; 
                    margin-bottom: 0.5rem;
                  "
                >
                  {{ user.name }}
                </div>
                <div 
                  class="profile-email" 
                  style="
                    font-size: 1.15rem; 
                    color: #a0aec0;
                  "
                >
                  {{ user.email }}
                </div>
              </div>
            </div>
          }
        `
      })
      export class ProfileComponent {
        protected auth = inject(AuthService);
      }
      ```
    </AuthCodeGroup>

    Now update the main App Component and add mise en forme:

    <Tabs>
      <Tab title="Composant de l’application">
        Remplacez le contenu du fichier composant de votre application (`src/app/app.ts` sur Angular 20+, ou `src/app/app.component.ts` sur Angular 19) :

        ```typescript src/app/app.ts expandable lines theme={null}
        import { Component, inject } from '@angular/core';
        import { AuthService } from '@auth0/auth0-angular';
        import { CommonModule } from '@angular/common';
        import { LoginButtonComponent } from './components/login-button.component';
        import { LogoutButtonComponent } from './components/logout-button.component';
        import { ProfileComponent } from './components/profile.component';

        @Component({
          selector: 'app-root',
          standalone: true,
          imports: [CommonModule, LoginButtonComponent, LogoutButtonComponent, ProfileComponent],
          template: `
            <div class="app-container">
              <!-- État de chargement -->
              @if (auth.isLoading$ | async) {
                <div class="loading-state">
                  <div class="loading-text">Loading...</div>
                </div>
              }

              <!-- État d'erreur -->
              @if (auth.error$ | async; as error) {
                <div class="error-state">
                  <div class="error-title">Oops!</div>
                  <div class="error-message">Something went wrong</div>
                  <div class="error-sub-message">{{ error.message }}</div>
                </div>
              }

              <!-- Contenu principal -->
              @if (!(auth.isLoading$ | async) && !(auth.error$ | async)) {
                <div class="main-card-wrapper">
                  <img 
                    src="https://cdn.auth0.com/quantum-assets/dist/latest/logos/auth0/auth0-lockup-en-ondark.png" 
                    alt="Auth0 Logo" 
                    class="auth0-logo"
                  />
                  <h1 class="main-title">Welcome to Sample0</h1>
                  
                  <!-- État authentifié -->
                  @if (auth.isAuthenticated$ | async) {
                    <div class="logged-in-section">
                      <div class="logged-in-message">✅ Successfully authenticated!</div>
                      <h2 class="profile-section-title">Your Profile</h2>
                      <div class="profile-card">
                        <app-profile />
                      </div>
                      <app-logout-button />
                    </div>
                  } @else {
                    <!-- État non authentifié -->
                    <div class="action-card">
                      <p class="action-text">Get started by signing in to your account</p>
                      <app-login-button />
                    </div>
                  }
                </div>
              }
            </div>
          `,
          styles: []
        })
        export class App {
          protected auth = inject(AuthService);
        }
        ```
      </Tab>

      <Tab title="Styles globaux">
        Ajoutez des styles à `src/styles.css` :

        ```css src/styles.css expandable lines theme={null}
        @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');

        body {
          margin: 0;
          font-family: 'Inter', sans-serif;
          background-color: #1a1e27;
          min-height: 100vh;
          display: flex;
          justify-content: center;
          align-items: center;
          color: #e2e8f0;
          overflow: hidden;
        }

        #root {
          width: 100%;
          height: 100%;
          display: flex;
          justify-content: center;
          align-items: center;
        }

        .app-container {
          display: flex;
          flex-direction: column;
          justify-content: center;
          align-items: center;
          min-height: 100vh;
          width: 100%;
          padding: 1rem;
          box-sizing: border-box;
        }

        .loading-state, .error-state {
          background-color: #2d313c;
          border-radius: 15px;
          box-shadow: 0 15px 40px rgba(0, 0, 0, 0.4);
          padding: 3rem;
          text-align: center;
        }

        .loading-text {
          font-size: 1.8rem;
          font-weight: 500;
          color: #a0aec0;
          animation: pulse 1.5s infinite ease-in-out;
        }

        .error-state {
          background-color: #c53030;
          color: #fff;
        }

        .error-title {
          font-size: 2.8rem;
          font-weight: 700;
          margin-bottom: 0.5rem;
        }

        .error-message {
          font-size: 1.3rem;
          margin-bottom: 0.5rem;
        }

        .error-sub-message {
          font-size: 1rem;
          opacity: 0.8;
        }

        .main-card-wrapper {
          background-color: #262a33;
          border-radius: 20px;
          box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.05);
          display: flex;
          flex-direction: column;
          align-items: center;
          gap: 2rem;
          padding: 3rem;
          max-width: 500px;
          width: 90%;
          animation: fadeInScale 0.8s ease-out forwards;
        }

        .auth0-logo {
          width: 160px;
          margin-bottom: 1.5rem;
          opacity: 0;
          animation: slideInDown 1s ease-out forwards 0.2s;
        }

        .main-title {
          font-size: 2.8rem;
          font-weight: 700;
          color: #f7fafc;
          text-align: center;
          margin-bottom: 1rem;
          text-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
          opacity: 0;
          animation: fadeIn 1s ease-out forwards 0.4s;
        }

        .action-card {
          background-color: #2d313c;
          border-radius: 15px;
          box-shadow: inset 0 2px 5px rgba(0, 0, 0, 0.3), 0 5px 15px rgba(0, 0, 0, 0.3);
          padding: 2.5rem;
          display: flex;
          flex-direction: column;
          align-items: center;
          gap: 1.8rem;
          width: calc(100% - 2rem);
          opacity: 0;
          animation: fadeIn 1s ease-out forwards 0.6s;
        }

        .action-text {
          font-size: 1.25rem;
          color: #cbd5e0;
          text-align: center;
          line-height: 1.6;
          font-weight: 400;
        }

        .button {
          padding: 1.1rem 2.8rem;
          font-size: 1.2rem;
          font-weight: 600;
          border-radius: 10px;
          border: none;
          cursor: pointer;
          transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
          box-shadow: 0 8px 20px rgba(0, 0, 0, 0.4);
          text-transform: uppercase;
          letter-spacing: 0.08em;
          outline: none;
        }

        .button:focus {
          box-shadow: 0 0 0 4px rgba(99, 179, 237, 0.5);
        }

        .button.login {
          background-color: #63b3ed;
          color: #1a1e27;
        }

        .button.login:hover {
          background-color: #4299e1;
          transform: translateY(-5px) scale(1.03);
          box-shadow: 0 12px 25px rgba(0, 0, 0, 0.5);
        }

        .button.logout {
          background-color: #fc8181;
          color: #1a1e27;
        }

        .button.logout:hover {
          background-color: #e53e3e;
          transform: translateY(-5px) scale(1.03);
          box-shadow: 0 12px 25px rgba(0, 0, 0, 0.5);
        }

        .logged-in-section {
          display: flex;
          flex-direction: column;
          align-items: center;
          gap: 1.5rem;
          width: 100%;
        }

        .logged-in-message {
          font-size: 1.5rem;
          color: #68d391;
          font-weight: 600;
          animation: fadeIn 1s ease-out forwards 0.8s;
        }

        .profile-section-title {
          font-size: 2.2rem;
          animation: slideInUp 1s ease-out forwards 1s;
        }

        .profile-card {
          padding: 2.2rem;
          animation: scaleIn 0.8s ease-out forwards 1.2s;
        }

        .profile-picture {
          width: 110px;
          transition: transform 0.3s ease-in-out;
        }

        .profile-picture:hover {
          transform: scale(1.05);
        }

        .profile-name {
          font-size: 2rem;
          margin-top: 0.5rem;
        }

        .profile-email {
          font-size: 1.15rem;
          text-align: center;
        }

        @keyframes fadeIn {
          from { opacity: 0; }
          to { opacity: 1; }
        }

        @keyframes fadeInScale {
          from { opacity: 0; transform: scale(0.95); }
          to { opacity: 1; transform: scale(1); }
        }

        @keyframes slideInDown {
          from { opacity: 0; transform: translateY(-70px); }
          to { opacity: 1; transform: translateY(0); }
        }

        @keyframes slideInUp {
          from { opacity: 0; transform: translateY(50px); }
          to { opacity: 1; transform: translateY(0); }
        }

        @keyframes pulse {
          0%, 100% { opacity: 1; }
          50% { opacity: 0.6; }
        }

        @keyframes scaleIn {
          from { opacity: 0; transform: scale(0.8); }
          to { opacity: 1; transform: scale(1); }
        }

        @media (max-width: 600px) {
          .main-card-wrapper {
            padding: 2rem;
            margin: 1rem;
          }
          
          .main-title {
            font-size: 2.2rem;
          }
          
          .button {
            padding: 1rem 2rem;
            font-size: 1.1rem;
          }
          
          .auth0-logo {
            width: 120px;
          }
        }
        ```
      </Tab>
    </Tabs>
  </Step>

  <Step title="Exécutez votre application" stepNumber={6}>
    ```shellscript theme={null}
    ng serve
    ```

    <Info>
      Si le port 4200 est déjà utilisé, exécutez : `ng serve --port 4201` et mettez à jour les URL de rappel de votre application Auth0 pour `http://localhost:4201`
    </Info>
  </Step>
</Steps>

<Check>
  **Vérification**

  Vous devriez maintenant avoir une page de connexion Auth0 entièrement fonctionnelle sur votre [localhost](http://localhost:4200/)
</Check>

***

<div id="advanced-usage">
  ## Utilisation avancée
</div>

<Accordion title="Utilisation de l’approche NgModule traditionnelle">
  Si vous avez créé votre projet avec `--standalone=false` ou si vous préférez utiliser des NgModules plutôt que des composants autonomes, voici comment configurer le SDK dans les projets générés par la CLI d’Angular 20+ :

  ```typescript src/main.ts theme={null}
  import { platformBrowser } from '@angular/platform-browser';
  import { AppModule } from './app/app-module';

  platformBrowser().bootstrapModule(AppModule)
    .catch((err) => console.error(err));
  ```

  ```typescript src/app/app-module.ts theme={null}
  import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core';
  import { BrowserModule } from '@angular/platform-browser';
  import { AuthModule } from '@auth0/auth0-angular';
  import { environment } from '../environments/environment';

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

  @NgModule({
    declarations: [App],
    imports: [
      BrowserModule,
      AppRoutingModule,
      AuthModule.forRoot({
        domain: environment.auth0.domain,
        clientId: environment.auth0.clientId,
        authorizationParams: {
          redirect_uri: window.location.origin
        }
      })
    ],
    providers: [provideBrowserGlobalErrorListeners()],
    bootstrap: [App]
  })
  export class AppModule { }
  ```

  <Note>
    Si vous utilisez **Angular 19**, les fichiers générés sont généralement `app.component.ts`, `app.module.ts` et `app-routing.module.ts`, et `main.ts` utilise `platformBrowserDynamic` au lieu de `platformBrowser`.

    **Angular 20+** génère `app.ts`, `app-module.ts` et `app-routing-module.ts` (sans points dans les noms de fichiers), et `main.ts` utilise `platformBrowser`, comme illustré ci-dessus.

    Dans tous les cas, les projets NgModule démarrent avec `bootstrapModule()` plutôt qu’avec l’approche `bootstrapApplication()` montrée dans le Quickstart principal.
  </Note>
</Accordion>

<Accordion title="Protéger les routes avec AuthGuard">
  Utilisez le garde fonctionnel moderne pour protéger les routes qui nécessitent une authentification :

  ```typescript src/app/app.routes.ts theme={null}
  import { Routes } from '@angular/router';
  import { authGuardFn } from '@auth0/auth0-angular';
  import { ProfileComponent } from './components/profile.component';

  export const routes: Routes = [
    {
      path: 'profile',
      component: ProfileComponent,
      canActivate: [authGuardFn]
    },
    {
      path: '',
      redirectTo: '/profile',
      pathMatch: 'full'
    }
  ];
  ```

  Ajoutez ensuite `provideAuth0` et le routeur à votre `app.config.ts` (si ce n’est pas déjà fait à l’étape 4) :

  ```typescript src/app/app.config.ts theme={null}
  import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
  import { provideRouter } from '@angular/router';
  import { provideAuth0 } from '@auth0/auth0-angular';
  import { environment } from '../environments/environment';
  import { routes } from './app.routes';

  export const appConfig: ApplicationConfig = {
    providers: [
      provideZoneChangeDetection({ eventCoalescing: true }),
      provideRouter(routes),
      provideAuth0({
        domain: environment.auth0.domain,
        clientId: environment.auth0.clientId,
        authorizationParams: {
          redirect_uri: window.location.origin
        }
      })
    ]
  };
  ```
</Accordion>

<Accordion title="Appeler des API protégées">
  Configurez l’intercepteur HTTP pour ajouter automatiquement des jetons aux appels d’API. Ajoutez `provideHttpClient` avec l’intercepteur Auth0 et une `audience` à votre `app.config.ts` :

  ```typescript src/app/app.config.ts theme={null}
  import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
  import { provideRouter } from '@angular/router';
  import { provideHttpClient, withInterceptors } from '@angular/common/http';
  import { provideAuth0, authHttpInterceptorFn } from '@auth0/auth0-angular';
  import { environment } from '../environments/environment';
  import { routes } from './app.routes';

  export const appConfig: ApplicationConfig = {
    providers: [
      provideZoneChangeDetection({ eventCoalescing: true }),
      provideRouter(routes),
      provideAuth0({
        domain: environment.auth0.domain,
        clientId: environment.auth0.clientId,
        authorizationParams: {
          redirect_uri: window.location.origin,
          audience: 'YOUR_API_IDENTIFIER'
        },
        httpInterceptor: {
          allowedList: [
            'http://localhost:3001/api/*'
          ]
        }
      }),
      provideHttpClient(
        withInterceptors([authHttpInterceptorFn])
      )
    ]
  };
  ```
</Accordion>
