> ## 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.

> Ce guide explique comment intégrer Auth0, ajouter l’authentification et afficher les informations du profil utilisateur dans une application Web Express.js à l’aide du SDK express-openid-connect.

# Ajouter la connexion à votre application Express

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 requis");
        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 de l'application :", 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 application Auth0</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 />;
};

<HowToSchema />

<Accordion title="Utilisez 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 des [agent skills](https://agentskills.io/home).

  **Installation :**

  ```bash theme={null}
  npx skills add https://github.com/auth0/agent-skills --skill auth0-express
  ```

  **Demandez ensuite à votre assistant IA :**

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

  Votre assistant IA créera automatiquement votre application Auth0, récupérera les identifiants, installera `express-openid-connect`, configurera le middleware et mettra en place vos routes. [Documentation complète des agent skills →](/fr-CA/docs/quickstart/agent-skills)
</Accordion>

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

  * [Node.js](https://nodejs.org/) 18 LTS ou version ultérieure
  * [npm](https://www.npmjs.com/) 10+ ou [yarn](https://yarnpkg.com/) 1.22+
  * [jq](https://jqlang.github.io/jq/) - Nécessaire pour configurer Auth0 CLI (facultatif)

  **Compatibilité des versions d’Express :** Ce guide de démarrage rapide est compatible avec Express 4.17.0 et les versions ultérieures.
</Note>

<div id="get-started">
  ## Premiers pas
</div>

Ce guide explique comment intégrer Auth0, ajouter l’authentification et afficher les informations du profil utilisateur dans une application Web Express.js à l’aide du SDK `express-openid-connect`.

***

<div id="1-create-a-new-project">
  ## 1. Créez un nouveau projet
</div>

Créez un nouveau répertoire pour votre application Express, puis initialisez un projet Node.js.

```bash theme={null}
mkdir auth0-express && cd auth0-express
```

```bash theme={null}
npm init -y
```

Créez la structure du projet :

```bash theme={null}
touch index.js .env
```

***

<div id="2-install-the-auth0-express-sdk">
  ## 2. Installer le SDK Auth0 pour Express
</div>

Installez `express-openid-connect` ainsi qu’Express et dotenv pour gérer les variables d’environnement.

```bash theme={null}
npm install express express-openid-connect dotenv
```

Pour le développement, installez nodemon pour redémarrer automatiquement votre serveur en cas de modification de fichiers :

```bash theme={null}
npm install --save-dev nodemon
```

Mettez à jour votre `package.json` pour y ajouter des scripts de lancement :

📁 **package.json**

```json theme={null}
{
  "name": "auth0-express",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "start": "node index.js",
    "dev": "nodemon index.js"
  },
  "dependencies": {
    "dotenv": "^16.3.1",
    "express": "^4.18.2",
    "express-openid-connect": "^2.17.1"
  },
  "devDependencies": {
    "nodemon": "^3.0.2"
  }
}
```

***

<div id="3-setup-your-auth0-app">
  ## 3. Configurez votre application Auth0
</div>

Ensuite, vous devez créer une nouvelle application dans votre locataire Auth0 et ajouter les variables d’environnement à votre projet.

Vous pouvez le faire automatiquement en exécutant une commande CLI ou manuellement dans l’Auth0 Dashboard :

<Tabs>
  <Tab title="CLI">
    Exécutez la commande shell suivante à la racine de votre projet pour créer une application Auth0 et générer votre fichier `.env` :

    **macOS / Linux :**

    ```bash theme={null}
    AUTH0_APP_NAME="My Express App" && \
    auth0 apps create -n "${AUTH0_APP_NAME}" -t regular \
      --callbacks http://localhost:3000 \
      --logout-urls http://localhost:3000 \
      --json | jq -r '"ISSUER_BASE_URL=https://\(.domain)\nCLIENT_ID=\(.client_id)\nSECRET='$(openssl rand -hex 32)'\nBASE_URL=http://localhost:3000"' > .env
    ```

    **Windows (PowerShell) :**

    ```powershell theme={null}
    $appName = "My Express App"
    auth0 apps create -n $appName -t regular `
      --callbacks http://localhost:3000 `
      --logout-urls http://localhost:3000 `
      --json | ConvertFrom-Json | ForEach-Object {
        "ISSUER_BASE_URL=https://$($_.domain)`nCLIENT_ID=$($_.client_id)`nSECRET=$([guid]::NewGuid().ToString())`nBASE_URL=http://localhost:3000"
      } | Out-File .env -Encoding utf8
    ```

    <Note>
      Si vous n’avez pas encore installé Auth0 CLI, exécutez :

      ```bash theme={null}
      brew tap auth0/auth0-cli && brew install auth0
      ```

      Authentifiez-vous ensuite avec `auth0 login`.
    </Note>
  </Tab>

  <Tab title="Dashboard">
    1. Accédez à l’[Auth0 Dashboard](https://manage.auth0.com/dashboard/)
    2. Accédez à **Applications** → **Create Application**
    3. Entrez un nom pour votre application (par exemple, « My Express App »)
    4. Sélectionnez **Regular Web Applications**, puis cliquez sur **Create**
    5. Dans l’onglet **Settings**, configurez les paramètres suivants :

    | Paramètre             | Valeur                  |
    | --------------------- | ----------------------- |
    | Allowed Callback URLs | `http://localhost:3000` |
    | Allowed Logout URLs   | `http://localhost:3000` |

    6. Faites défiler la page vers le bas, puis cliquez sur **Save Changes**
    7. Copiez les valeurs **Domain** et **Client ID** de la section **Basic Information**

    Créez votre fichier `.env` avec les valeurs suivantes :

    📁 **.env**

    ```bash theme={null}
    ISSUER_BASE_URL=https://YOUR_AUTH0_DOMAIN
    CLIENT_ID=YOUR_CLIENT_ID
    SECRET=use-a-long-random-string-at-least-32-characters
    BASE_URL=http://localhost:3000
    ```

    <Warning>
      Remplacez `YOUR_AUTH0_DOMAIN` par le domaine de votre locataire Auth0 (par exemple, `dev-abc123.us.auth0.com`) et `YOUR_CLIENT_ID` par l’ID client de votre application dans le dashboard.
    </Warning>

    Générez un secret sécurisé pour le chiffrement de la session :

    ```bash theme={null}
    openssl rand -hex 32
    ```

    Copiez le résultat et utilisez-le comme valeur de `SECRET` dans votre fichier `.env`.
  </Tab>
</Tabs>

***

<div id="4-configure-the-middleware">
  ## 4. Configurez le middleware
</div>

Ajoutez le middleware Auth0 à votre application Express. Le middleware `auth()` assure la gestion des sessions et crée automatiquement les routes `/login`, `/logout` et `/callback`.

📁 **index.js**

```javascript theme={null}
require('dotenv').config();
const express = require('express');
const { auth } = require('express-openid-connect');

const app = express();
const port = process.env.PORT || 3000;

// Configuration Auth0
const config = {
  authRequired: false,      // Autoriser les routes publiques
  auth0Logout: true,        // Utiliser le point de terminaison de déconnexion Auth0
  secret: process.env.SECRET,
  baseURL: process.env.BASE_URL,
  clientID: process.env.CLIENT_ID,
  issuerBaseURL: process.env.ISSUER_BASE_URL,
};

// Appliquer le middleware d'authentification
app.use(auth(config));

// Route d'accueil - publique
app.get('/', (req, res) => {
  res.send(req.oidc.isAuthenticated() ? 'Logged in' : 'Logged out');
});

app.listen(port, () => {
  console.log(`Server running at http://localhost:${port}`);
});
```

**Ce que cela fait :**

* `authRequired: false` permet, par défaut, aux utilisateurs authentifiés et non authentifiés d’accéder aux routes
* `auth0Logout: true` garantit que les utilisateurs sont déconnectés d’Auth0 ainsi que de votre application
* Le middleware fournit automatiquement les routes `/login`, `/logout` et `/callback`
* La session de l’utilisateur est stockée dans un témoin chiffré

***

<div id="5-create-login-logout-and-profile-routes">
  ## 5. Créez les routes de connexion, de déconnexion et de profil
</div>

Ajoutez maintenant des routes pour afficher les liens de connexion et de déconnexion, ainsi qu’une page de profil protégée.

📁 **index.js**

```javascript theme={null}
require('dotenv').config();
const express = require('express');
const { auth, requiresAuth } = require('express-openid-connect');

const app = express();
const port = process.env.PORT || 3000;

// Configuration Auth0
const config = {
  authRequired: false,
  auth0Logout: true,
  secret: process.env.SECRET,
  baseURL: process.env.BASE_URL,
  clientID: process.env.CLIENT_ID,
  issuerBaseURL: process.env.ISSUER_BASE_URL,
};

// Appliquer le middleware d'authentification
app.use(auth(config));

// Route d'accueil - affiche le statut de connexion/déconnexion
app.get('/', (req, res) => {
  const isAuthenticated = req.oidc.isAuthenticated();

  res.send(`
    <html>
      <head>
        <title>Auth0 Express Quickstart</title>
        <style>
          body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; padding: 2rem; max-width: 600px; margin: 0 auto; }
          a { color: #0066cc; text-decoration: none; margin-right: 1rem; }
          a:hover { text-decoration: underline; }
          .status { padding: 1rem; border-radius: 4px; margin: 1rem 0; }
          .logged-in { background: #d4edda; color: #155724; }
          .logged-out { background: #f8d7da; color: #721c24; }
        </style>
      </head>
      <body>
        <h1>Auth0 Express Quickstart</h1>
        <div class="status ${isAuthenticated ? 'logged-in' : 'logged-out'}">
          ${isAuthenticated ? '✓ You are logged in' : '✗ You are logged out'}
        </div>
        <nav>
          ${isAuthenticated
            ? '<a href="/profile">Profile</a> | <a href="/logout">Logout</a>'
            : '<a href="/login">Login</a>'}
        </nav>
      </body>
    </html>
  `);
});

// Route de profil protégée - nécessite une authentification
app.get('/profile', requiresAuth(), (req, res) => {
  const user = req.oidc.user;

  res.send(`
    <html>
      <head>
        <title>Profile - Auth0 Express</title>
        <style>
          body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; padding: 2rem; max-width: 600px; margin: 0 auto; }
          a { color: #0066cc; text-decoration: none; }
          img { border-radius: 50%; }
          pre { background: #f4f4f4; padding: 1rem; border-radius: 4px; overflow-x: auto; }
          .card { border: 1px solid #ddd; border-radius: 8px; padding: 1.5rem; margin: 1rem 0; }
        </style>
      </head>
      <body>
        <h1>User Profile</h1>
        <div class="card">
          ${user.picture ? `<img src="${user.picture}" alt="Profile" width="80" />` : ''}
          <h2>${user.name || user.nickname || 'User'}</h2>
          <p><strong>Email:</strong> ${user.email || 'N/A'}</p>
        </div>
        <h3>Full User Object</h3>
        <pre>${JSON.stringify(user, null, 2)}</pre>
        <nav>
          <a href="/">← Back to Home</a> | <a href="/logout">Logout</a>
        </nav>
      </body>
    </html>
  `);
});

app.listen(port, () => {
  console.log(`Server running at http://localhost:${port}`);
});
```

**Points clés :**

* Le middleware `requiresAuth()` protège la route `/profile` : les utilisateurs non authentifiés sont redirigés vers la page de connexion
* `req.oidc.user` contient les informations de profil de l’utilisateur authentifié
* `req.oidc.isAuthenticated()` retourne un booléen indiquant l’état de la connexion
* Les routes de connexion et de déconnexion (`/login`, `/logout`) sont créées automatiquement par le middleware `auth()`

***

<div id="6-run-your-app">
  ## 6. Exécutez votre application
</div>

Démarrez le serveur de développement :

```bash theme={null}
npm run dev
```

Ouvrez [http://localhost:3000](http://localhost:3000) dans votre navigateur.

<Check>
  **Point de vérification**

  Vous devriez maintenant disposer d’une page de connexion Auth0 entièrement fonctionnelle. Lorsque vous :

  1. Cliquez sur "Login" - vous êtes redirigé vers la page Universal Login d’Auth0
  2. Terminez l’authentification - vous êtes redirigé vers votre application
  3. Accédez à "/profile" - vous voyez vos informations d’utilisateur
  4. Cliquez sur "Logout" - vous êtes déconnecté à la fois de votre application et d’Auth0
</Check>

***

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

<AccordionGroup>
  <Accordion title="Protéger certaines routes avec requiresAuth()">
    Utilisez le middleware `requiresAuth()` pour protéger chaque route qui nécessite une authentification :

    ```javascript theme={null}
    const { auth, requiresAuth } = require('express-openid-connect');

    app.use(auth({ authRequired: false }));

    // Route publique
    app.get('/', (req, res) => {
      res.send('Welcome! This is public.');
    });

    // Routes protégées
    app.get('/dashboard', requiresAuth(), (req, res) => {
      res.send(`Hello ${req.oidc.user.name}, welcome to your dashboard!`);
    });

    app.get('/settings', requiresAuth(), (req, res) => {
      res.send('Settings page - only for authenticated users');
    });
    ```

    Vous pouvez également protéger toutes les routes d’un chemin donné à l’aide d’Express Router :

    ```javascript theme={null}
    const protectedRouter = express.Router();

    // Toutes les routes de ce routeur nécessitent une authentification
    protectedRouter.use(requiresAuth());

    protectedRouter.get('/dashboard', (req, res) => {
      res.send('Protected dashboard');
    });

    protectedRouter.get('/settings', (req, res) => {
      res.send('Protected settings');
    });

    app.use('/app', protectedRouter);
    // Routes : /app/dashboard, /app/settings sont toutes protégées
    ```
  </Accordion>

  <Accordion title="Utiliser des jetons d’accès pour appeler des API protégées">
    Pour appeler des API externes qui nécessitent un jeton d’accès, configurez le SDK pour en demander un :

    📁 **index.js** (configuration mise à jour)

    ```javascript theme={null}
    const config = {
      authRequired: false,
      auth0Logout: true,
      secret: process.env.SECRET,
      baseURL: process.env.BASE_URL,
      clientID: process.env.CLIENT_ID,
      issuerBaseURL: process.env.ISSUER_BASE_URL,
      clientSecret: process.env.CLIENT_SECRET,  // Requis pour le flux de code
      authorizationParams: {
        response_type: 'code',
        audience: process.env.API_AUDIENCE,     // Your API identifier
        scope: 'openid profile email read:data',
      },
    };
    ```

    Ajoutez les éléments suivants à votre fichier `.env` :

    ```bash theme={null}
    CLIENT_SECRET=your_client_secret_from_dashboard
    API_AUDIENCE=https://your-api.example.com
    ```

    Utilisez ensuite le jeton d’accès pour appeler votre API :

    ```javascript theme={null}
    app.get('/api-data', requiresAuth(), async (req, res) => {
      try {
        let { token_type, access_token, isExpired, refresh } = req.oidc.accessToken;

        // Actualiser le jeton s'il est expiré
        if (isExpired()) {
          const refreshed = await refresh();
          access_token = refreshed.access_token;
        }

        // Appeler votre API protégée
        const response = await fetch('https://your-api.example.com/data', {
          headers: {
            Authorization: `${token_type} ${access_token}`,
          },
        });

        const data = await response.json();
        res.json(data);
      } catch (error) {
        console.error('API call failed:', error);
        res.status(500).json({ error: 'Failed to fetch data' });
      }
    });
    ```

    <Note>
      Pour obtenir des jetons d’actualisation, ajoutez `offline_access` à votre scope :

      ```javascript theme={null}
      scope: 'openid profile email offline_access read:data',
      ```
    </Note>
  </Accordion>

  <Accordion title="Utilisation de l’autorisation fondée sur les revendications">
    Protégez les routes selon les claim de l’utilisateur (rôles, autorisations, etc.):

    ```javascript theme={null}
    const { auth, requiresAuth, claimEquals, claimIncludes, claimCheck } = require('express-openid-connect');

    app.use(auth({ authRequired: false }));

    // Uniquement les utilisateurs avec le rôle = 'admin'
    app.get('/admin', claimEquals('role', 'admin'), (req, res) => {
      res.send('Admin dashboard');
    });

    // Utilisateurs dont le tableau de rôles contient 'editor'
    app.get('/editor', claimIncludes('roles', 'editor'), (req, res) => {
      res.send('Editor dashboard');
    });

    // Vérification de revendication personnalisée avec logique
    app.get('/premium', claimCheck((req, claims) => {
      return claims.subscription === 'premium' || claims.role === 'admin';
    }), (req, res) => {
      res.send('Premium content');
    });
    ```

    <Note>
      Les revendications comme `role` doivent être ajoutées à vos jetons au moyen des Rules ou des Actions d’Auth0. [En savoir plus sur l’ajout de revendications personnalisées](https://auth0.com/docs/customize/actions/flows-and-triggers/login-flow/add-user-roles-to-id-and-access-tokens).
    </Note>
  </Accordion>

  <Accordion title="Magasin de sessions personnalisé (Redis)">
    Pour les environnements de production, ou lorsque vous exécutez plusieurs instances de serveur, utilisez un stockage de session personnalisé :

    ```bash theme={null}
    npm install redis connect-redis
    ```

    ```javascript theme={null}
    const { auth } = require('express-openid-connect');
    const { createClient } = require('redis');
    const RedisStore = require('connect-redis').default;

    // Créer le client Redis
    const redisClient = createClient({
      url: process.env.REDIS_URL || 'redis://localhost:6379',
    });
    redisClient.connect().catch(console.error);

    const config = {
      authRequired: false,
      auth0Logout: true,
      secret: process.env.SECRET,
      baseURL: process.env.BASE_URL,
      clientID: process.env.CLIENT_ID,
      issuerBaseURL: process.env.ISSUER_BASE_URL,
      session: {
        store: new RedisStore({ client: redisClient }),
      },
    };

    app.use(auth(config));
    ```

    **Quand utiliser un stockage de sessions personnalisé :**

    * Exécution de plusieurs instances de serveur (répartition de charge)
    * Les données de session dépassent la taille limite d’un témoin (\~4 KB)
    * Besoin de conserver les sessions entre les redémarrages du serveur
    * Utilisation de la déconnexion par canal arrière
  </Accordion>

  <Accordion title="Gestion des erreurs">
    Ajoutez une gestion appropriée des erreurs d’authentification :

    ```javascript theme={null}
    const { auth } = require('express-openid-connect');

    app.use(auth({
      authRequired: false,
      auth0Logout: true,
      secret: process.env.SECRET,
      baseURL: process.env.BASE_URL,
      clientID: process.env.CLIENT_ID,
      issuerBaseURL: process.env.ISSUER_BASE_URL,
      errorOnRequiredAuth: true,  // Renvoyer 401 au lieu de rediriger pour les routes API
    }));

    // Gestionnaire d'erreurs personnalisé
    app.use((err, req, res, next) => {
      // Gérer les erreurs d'authentification
      if (err.statusCode === 401) {
        // Pour les requêtes API, renvoyer du JSON
        if (req.accepts('json')) {
          return res.status(401).json({
            error: 'Authentication required',
            login_url: '/login',
          });
        }
        // Pour les requêtes du navigateur, rediriger vers la page de connexion
        return res.redirect('/login');
      }

      // Journaliser l'erreur (ne pas exposer les détails au client)
      console.error('Application error:', err.message);

      res.status(err.statusCode || 500).json({
        error: 'An unexpected error occurred',
      });
    });
    ```
  </Accordion>
</AccordionGroup>

***

<div id="troubleshooting">
  ## Dépannage
</div>

<AccordionGroup>
  <Accordion title="Problèmes courants et solutions">
    ### Erreur « Invalid state » après la connexion

    **Problème :** Le paramètre `state` ne correspond pas entre la requête d’authentification et le callback.

    **Solutions :**

    1. Assurez-vous d’utiliser HTTPS en production
    2. Vérifiez que les témoins sont correctement définis (et non bloqués par le navigateur)
    3. Vérifiez que l’URL de retour correspond exactement dans Auth0 Dashboard

    ### `req.oidc` est `undefined`

    **Problème :** Le middleware `auth()` n’est pas appliqué avant l’accès à `req.oidc`.

    **Solution :** Assurez-vous que `app.use(auth(config))` est appelé avant toute route qui accède à `req.oidc` :

    ```javascript theme={null}
    // ✅ Ordre correct
    app.use(auth(config));
    app.get('/profile', requiresAuth(), (req, res) => { ... });

    // ❌ Mauvais ordre
    app.get('/profile', requiresAuth(), (req, res) => { ... });
    app.use(auth(config));
    ```

    ### Session trop volumineuse / erreurs liées aux témoins

    **Problème :** Les données de session de l’utilisateur dépassent la taille limite des témoins.

    **Solution :** Utilisez un stockage de session personnalisé, comme Redis :

    ```javascript theme={null}
    session: {
      store: new RedisStore({ client: redisClient }),
    }
    ```

    ### URL de retour non correspondante

    **Problème :** Erreur « Callback URL mismatch » renvoyée par Auth0.

    **Solution :**

    1. Accédez à Auth0 Dashboard → Applications → Votre application → Settings
    2. Ajoutez `http://localhost:3000` (ou votre URL de production) à **Allowed Callback URLs**
    3. L’URL doit correspondre **exactement** (y compris les barres obliques finales)

    ### Les variables d’environnement ne se chargent pas

    **Problème :** Les valeurs de configuration sont `undefined`.

    **Solution :**

    1. Assurez-vous que `require('dotenv').config()` se trouve en haut de votre fichier d’entrée
    2. Vérifiez que le fichier `.env` se trouve dans le répertoire racine
    3. Vérifiez qu’il n’y a pas de fautes de frappe dans les noms de variables

    ```javascript theme={null}
    // Débogage : consignez les valeurs de configuration (à supprimer en production !)
    console.log('Config check:', {
      hasSecret: !!process.env.SECRET,
      hasClientID: !!process.env.CLIENT_ID,
      issuerBaseURL: process.env.ISSUER_BASE_URL,
    });
    ```
  </Accordion>
</AccordionGroup>

***

<div id="next-steps">
  ## Étapes suivantes
</div>

Maintenant que l’authentification fonctionne, vous pouvez aussi explorer :

* **[Ajouter l’autorisation](https://auth0.com/docs/manage-users/access-control/rbac)** - Implémentez le contrôle d’accès basé sur les rôles
* **[Appeler des API protégées](https://auth0.com/docs/secure/tokens/access-tokens/get-access-tokens)** - Utilisez des jetons d’accès pour appeler vos API backend
* **[Personnaliser Universal Login](https://auth0.com/docs/customize/universal-login-pages)** - Adaptez l’image de marque de votre expérience de connexion
* **[Ajouter des connexions sociales](https://auth0.com/docs/connections/social)** - Activez Google, GitHub et d’autres options de connexion sociale
* **[Implémenter MFA](https://auth0.com/docs/secure/multi-factor-authentication)** - Ajoutez l’authentification multifacteur

***

<div id="resources">
  ## Ressources
</div>

* **[express-openid-connect GitHub](https://github.com/auth0/express-openid-connect)** - Code source et exemples
* **[Documentation de l’API](https://auth0.github.io/express-openid-connect/)** - Référence complète de l’API
* **[Application d’exemple Express d’Auth0](https://github.com/auth0-samples/auth0-express-webapp-sample)** - Application d’exemple complète
* **[Communauté Auth0](https://community.auth0.com/)** - Obtenez de l’aide auprès de la communauté
