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

# Protégez votre API Express.js

> Ce guide explique comment protéger les points de terminaison d’une API Express.js à l’aide de jetons d’accès JWT avec le SDK express-oauth2-jwt-bearer.

Une nouvelle version **Beta** de ce Quickstart est maintenant offerte avec le SDK `@auth0/auth0-express-api`, qui remplacera bientôt ce guide. [Essayer le Quickstart Beta →](https://auth0.com/docs/fr-ca/quickstart/backend/express-api-beta.md)

> **Utiliser l’IA pour intégrer Auth0**
>
> Si vous utilisez un assistant de codage IA comme Claude Code, Cursor ou GitHub Copilot, vous pouvez ajouter automatiquement l’authentification de l’API 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 JWT authentication to my Express API
> ```
>
> Votre assistant IA créera automatiquement votre API Auth0, récupérera les identifiants, installera `express-oauth2-jwt-bearer`, configurera le middleware JWT et protégera vos points de terminaison d’API grâce à la validation des tokens. [Documentation complète sur Agent Skills →](https://auth0.com/docs/fr-ca/quickstart/agent-skills.md)

> [!NOTE]
>
> **Prérequis :** Avant de commencer, assurez-vous d’avoir installé ce qui suit :
>
> * **[Node.js](https://nodejs.org/en/download)** 18 LTS ou une version ultérieure (prend en charge `^18.12.0 || ^20.2.0 || ^22.1.0 || ^24.0.0`)
> * **[npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)** 8+ ou **[yarn](https://classic.yarnpkg.com/lang/en/docs/install/)** 1.22+ ou **[pnpm](https://pnpm.io/installation)** 8+
>
> Vérifiez l’installation : `node --version && npm --version`
>
> **Compatibilité des versions d’Express :** Ce Quickstart fonctionne avec **Express 4.x** et **Express 5.x**.

## Pour commencer

Ce Quickstart montre comment protéger des points de terminaison d’API Express.js à l’aide de jetons d’accès JWT. Vous allez créer une API sécurisée qui valide les jetons d’accès Auth0, protège des routes et met en œuvre une autorisation basée sur les scopes.

**1. Créer un nouveau projet**

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

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

Initialiser le projet

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

Créer la structure du projet

```shellscript theme={null}
touch server.js .env
```

**2. Installer le SDK express-oauth2-jwt-bearer**

Installez les dépendances nécessaires

```shellscript theme={null}
npm install express express-oauth2-jwt-bearer dotenv
```

Ajoutez des scripts `start` à votre `package.json` :

```json package.json theme={null}
{
  "scripts": {
    "start": "node server.js",
    "dev": "node --watch server.js"
  }
}
```

**3. Configurez votre API Auth0**

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

Vous avez deux options pour configurer votre API Auth0 : utiliser une commande CLI ou passer par le Dashboard manuellement :

**CLI**

Exécutez la commande suivante à la racine de votre projet pour créer une API Auth0 :

```shellscript Mac theme={null}
# Installer Auth0 CLI (si ce n’est pas déjà fait)
brew tap auth0/auth0-cli && brew install auth0

# Créer une API Auth0
auth0 apis create \
  --name "My Express API" \
  --identifier https://my-express-api.example.com
```

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

# Créer une API Auth0
auth0 apis create `
  --name "My Express API" `
  --identifier https://my-express-api.example.com
```

> [!NOTE]
>
> Cette commande va :
>
> 1. Vérifier si vous êtes authentifié (et vous inviter à vous connecter au besoin)
> 2. Créer une API Auth0 avec l’identifiant indiqué
> 3. Afficher les détails de l’API, y compris le domaine et l’identifiant

Une fois l’API créée, copiez les valeurs **Identifier** et **Domain**, puis créez votre fichier `.env` :

```bash .env theme={null}
AUTH0_DOMAIN=YOUR_AUTH0_DOMAIN
AUTH0_AUDIENCE=YOUR_API_IDENTIFIER
```

> [!NOTE]
>
> Remplacez `YOUR_AUTH0_DOMAIN` par le domaine de votre tenant Auth0 (par exemple, `dev-abc123.us.auth0.com`) et `YOUR_API_IDENTIFIER` par l’identifiant de votre API (par exemple, `https://my-express-api.example.com`).

**Dashboard**

1. Accédez au [Auth0 Dashboard](https://manage.auth0.com/dashboard/)
2. Allez à **Applications** → **APIs** → **Create API**
3. Saisissez un nom pour votre API (par exemple, "My Express API")
4. Définissez l’**Identifier** (par exemple, `https://my-express-api.example.com`)
   * Il s’agit de l’audience de votre API et elle doit respecter un format d’URL valide
   * Il n’est pas nécessaire qu’il s’agisse d’une vraie URL : c’est simplement un identifiant
5. Laissez **Signing Algorithm** à **RS256**
6. Cliquez sur **Create**
7. Copiez la valeur **Identifier** depuis l’onglet **Settings**

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

```bash .env theme={null}
AUTH0_DOMAIN=YOUR_AUTH0_DOMAIN
AUTH0_AUDIENCE=YOUR_API_IDENTIFIER
```

> [!NOTE]
>
> Remplacez `YOUR_AUTH0_DOMAIN` par le domaine de votre tenant Auth0 (par exemple, `dev-abc123.us.auth0.com`) et `YOUR_API_IDENTIFIER` par l’identifiant de votre API dans le dashboard (par exemple, `https://my-express-api.example.com`).

> [!TIP]
>
> Vérifiez que votre fichier `.env` existe : `cat .env` (Mac/Linux) ou `type .env` (Windows)

**4. Configurer le middleware JWT**

Créez votre serveur Express et configurez la validation JWT :

```javascript server.js {1-3,6-7,10-13} lines theme={null}
require('dotenv').config();
const express = require('express');
const { auth } = require('express-oauth2-jwt-bearer');

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

// Configurer le middleware de validation JWT
const checkJwt = auth({
  issuerBaseURL: `https://${process.env.AUTH0_DOMAIN}`,
  audience: process.env.AUTH0_AUDIENCE,
});

// Démarrer le serveur
app.listen(port, () => {
  console.log(`API server running at http://localhost:${port}`);
});
```

**Ce que cela fait :**

* Crée un middleware de validation JWT à l’aide de votre domaine Auth0 et de l’audience de l’API
* Valide les claims `iss` et `aud` des jetons d’accès reçus
* Met `checkJwt` à disposition pour protéger des routes précises

**5. Créer des routes d’API**

Ajoutez des routes publiques et protégées à votre `server.js` :

```javascript server.js expandable lines theme={null}
require('dotenv').config();
const express = require('express');
const { auth, requiredScopes } = require('express-oauth2-jwt-bearer');

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

// Configurer le middleware de validation JWT
const checkJwt = auth({
  issuerBaseURL: `https://${process.env.AUTH0_DOMAIN}`,
  audience: process.env.AUTH0_AUDIENCE,
});

// Route publique - aucune authentification requise
app.get('/api/public', (req, res) => {
  res.json({
    message: 'Hello from a public endpoint! You don\'t need to be authenticated to see this.',
    timestamp: new Date().toISOString(),
  });
});

// Route protégée - nécessite un access token valide
app.get('/api/private', checkJwt, (req, res) => {
  res.json({
    message: 'Hello from a protected endpoint! You successfully authenticated.',
    user: req.auth.payload.sub,
    timestamp: new Date().toISOString(),
  });
});

// Route protégée avec scope - nécessite le scope 'read:messages'
app.get('/api/private-scoped', checkJwt, requiredScopes('read:messages'), (req, res) => {
  res.json({
    message: 'Hello from a scoped endpoint! You have the required permission.',
    user: req.auth.payload.sub,
    scope: req.auth.payload.scope,
    timestamp: new Date().toISOString(),
  });
});

// Middleware de gestion des erreurs
app.use((err, req, res, next) => {
  const status = err.status || 500;
  const message = err.message || 'Internal Server Error';

  res.status(status).json({
    error: err.code || 'server_error',
    message: status === 401 ? 'Authentication required' : message,
  });
});

// Démarrer le serveur
app.listen(port, () => {
  console.log(`API server running at http://localhost:${port}`);
});
```

**Points clés :**

* Les routes publiques ne nécessitent pas d'authentification
* Les routes protégées utilisent le middleware `checkJwt` pour exiger un JWT valide
* Les routes avec scopes utilisent `requiredScopes()` pour exiger des permissions précises dans le token
* `req.auth.payload` contient les claims JWT décodés pour les requêtes authentifiées
* Le claim `sub` contient l'identifiant unique de l'utilisateur

**6. Lancez votre API**

Démarrez le serveur de développement :

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

Votre API est maintenant accessible à l’adresse [http://localhost:3001](http://localhost:3001).

> [!NOTE]
>
> L’option `--watch` de Node.js 18+ redémarre automatiquement le serveur lorsque des fichiers sont modifiés.

**7. Testez votre API**

Testez le point de terminaison public (aucune authentification requise) :

```bash theme={null}
curl http://localhost:3001/api/public
```

Vous devriez voir :

```json theme={null}
{
  "message": "Hello from a public endpoint! You don't need to be authenticated to see this.",
  "timestamp": "2024-01-15T10:30:00.000Z"
}
```

Testez l’endpoint protégé sans token (cela devrait échouer) :

```bash theme={null}
curl http://localhost:3001/api/private
```

Vous devriez voir une erreur 401 Unauthorized :

```json theme={null}
{
  "error": "unauthorized",
  "message": "Authentication required"
}
```

Pour tester avec un jeton valide :

1. Accédez à [Auth0 Dashboard](https://manage.auth0.com/) → **Applications** → **APIs**
2. Sélectionnez votre API → onglet **Test**
3. Copiez le jeton d’accès généré

Testez votre point de terminaison protégé :

```bash theme={null}
curl http://localhost:3001/api/private \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
```

Vous devriez voir :

```json theme={null}
{
  "message": "Hello from a protected endpoint! You successfully authenticated.",
  "user": "auth0|abc123...",
  "timestamp": "2024-01-15T10:30:00.000Z"
}
```

> [!TIP]
>
> **Vérification**
>
> Vous devriez maintenant avoir une API protégée. Votre API :
>
> 1. Accepte les requêtes vers des points de terminaison publics sans authentification
> 2. Rejette les requêtes vers des points de terminaison protégés sans jeton valide
> 3. Valide les jetons JWT à l’aide de votre domaine Auth0 et de l’audience
> 4. Fournit des renseignements sur l’utilisateur à partir des claims du jeton au moyen de `req.auth.payload`

***

## Utilisation avancée

> **Autorisation basée sur les scopes**
>
> Les scopes permettent un contrôle d’accès granulaire. Vous pouvez exiger des scopes précis pour différents points de terminaison.
>
> **Configurer les scopes dans Auth0 :**
>
> 1. Dans le [Auth0 Dashboard](https://manage.auth0.com/), accédez à **Applications** → **APIs** → votre API
> 2. Accédez à l’onglet **Permissions**
> 3. Ajoutez des permissions comme `read:messages`, `write:messages`, `admin:access`
>
> **Protéger des routes avec des scopes :**
>
> ```javascript server.js theme={null}
> const { auth, requiredScopes } = require('express-oauth2-jwt-bearer');
>
> // Exige le scope 'read:messages'
> app.get('/api/messages', checkJwt, requiredScopes('read:messages'), (req, res) => {
>   res.json({
>     messages: [
>       { id: 1, text: 'Hello!' },
>       { id: 2, text: 'World!' },
>     ],
>   });
> });
>
> // Exige le scope 'admin:access'
> app.get('/api/admin', checkJwt, requiredScopes('admin:access'), (req, res) => {
>   res.json({
>     message: 'Admin access granted',
>     userId: req.auth.payload.sub,
>   });
> });
> ```
>
> > [!NOTE]
> >
> > Si une requête ne contient pas le scope requis, l’API renvoie `403 Forbidden` avec une erreur `insufficient_scope`. Assurez-vous que l’application cliente demande les bons scopes lors de l’obtention d’un jeton d’accès.

> **Validation de claims personnalisées**
>
> En plus des scopes, vous pouvez valider des claims personnalisées dans le payload JWT :
>
> ```javascript server.js theme={null}
> const { auth, claimEquals, claimIncludes, claimCheck } = require('express-oauth2-jwt-bearer');
>
> // Exige une valeur exacte de claim
> app.get('/api/org/:orgId',
>   checkJwt,
>   claimEquals('org_id', 'org_123'),
>   (req, res) => {
>     res.json({ message: 'Organization access granted' });
>   }
> );
>
> // Exige que la claim inclue toutes les valeurs précisées
> app.get('/api/roles',
>   checkJwt,
>   claimIncludes('roles', 'editor', 'viewer'),
>   (req, res) => {
>     res.json({ message: 'Role check passed' });
>   }
> );
>
> // Logique de validation de claim personnalisée
> app.get('/api/premium',
>   checkJwt,
>   claimCheck((claims) => {
>     return claims.subscription === 'premium' && claims.verified === true;
>   }),
>   (req, res) => {
>     res.json({ message: 'Premium feature access granted' });
>   }
> );
> ```
>
> > [!NOTE]
> >
> > Les claims personnalisées doivent utiliser des URL avec espace de noms (p. ex., `https://myapp.com/roles`), à moins qu’il ne s’agisse de claims OIDC standard. [En savoir plus sur les claims personnalisées](https://auth0.com/docs/fr-ca/secure/tokens/json-web-tokens/create-custom-claims.md).

> **Authentification facultative (routes publiques/privées mixtes)**
>
> Permettez l’accès authentifié et anonyme à une même route :
>
> ```javascript server.js theme={null}
> const optionalAuth = auth({
>   issuerBaseURL: `https://${process.env.AUTH0_DOMAIN}`,
>   audience: process.env.AUTH0_AUDIENCE,
>   authRequired: false,
> });
>
> app.get('/api/feed', optionalAuth, (req, res) => {
>   if (req.auth) {
>     res.json({
>       message: `Welcome back, ${req.auth.payload.sub}!`,
>       personalizedContent: true,
>     });
>   } else {
>     res.json({
>       message: 'Welcome, guest!',
>       personalizedContent: false,
>     });
>   }
> });
> ```

> **Configuration CORS**
>
> Activez CORS pour autoriser les requêtes provenant d’applications Web :
>
> ```bash theme={null}
> npm install cors
> ```
>
> ```javascript server.js theme={null}
> const cors = require('cors');
>
> app.use(cors({
>   origin: ['http://localhost:3000', 'http://localhost:5173'],
>   allowedHeaders: ['Authorization', 'Content-Type'],
>   exposedHeaders: ['WWW-Authenticate'],
> }));
> ```
>
> En Production, précisez les origines exactes :
>
> ```javascript server.js theme={null}
> app.use(cors({
>   origin: [
>     'https://myapp.com',
>     'https://www.myapp.com'
>   ],
>   credentials: true,
>   methods: ['GET', 'POST', 'PUT', 'DELETE'],
> }));
> ```

> **Gestion personnalisée des erreurs**
>
> Ajoutez une gestion complète des erreurs d’authentification :
>
> ```javascript server.js theme={null}
> const { UnauthorizedError, InvalidTokenError, InsufficientScopeError } = require('express-oauth2-jwt-bearer');
>
> app.use((err, req, res, next) => {
>   if (err instanceof InsufficientScopeError) {
>     return res.status(403).json({
>       error: 'forbidden',
>       message: 'You do not have permission to access this resource',
>       required_scopes: err.requiredScopes,
>     });
>   }
>
>   if (err instanceof InvalidTokenError) {
>     return res.status(401).json({
>       error: 'invalid_token',
>       message: 'The provided token is invalid or expired',
>     });
>   }
>
>   if (err instanceof UnauthorizedError) {
>     return res.status(401).set(err.headers).json({
>       error: 'unauthorized',
>       message: 'Authentication required',
>     });
>   }
>
>   next(err);
> });
> ```

> **Prise en charge de TypeScript**
>
> Pour les projets TypeScript, installez les définitions de types et configurez votre projet :
>
> ```bash theme={null}
> npm install -D typescript @types/express @types/node
> ```
>
> Créez `server.ts` :
>
> ```typescript server.ts theme={null}
> import 'dotenv/config';
> import express, { Request, Response, NextFunction } from 'express';
> import { auth, requiredScopes, UnauthorizedError } from 'express-oauth2-jwt-bearer';
>
> const app = express();
> const port = process.env.PORT || 3001;
>
> const checkJwt = auth({
>   issuerBaseURL: `https://${process.env.AUTH0_DOMAIN}`,
>   audience: process.env.AUTH0_AUDIENCE,
> });
>
> app.get('/api/public', (req: Request, res: Response) => {
>   res.json({ message: 'Public endpoint - no authentication required' });
> });
>
> app.get('/api/private', checkJwt, (req: Request, res: Response) => {
>   res.json({
>     message: 'Private endpoint',
>     user: req.auth?.payload.sub,
>   });
> });
>
> app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
>   if (err instanceof UnauthorizedError) {
>     res.status(err.status).set(err.headers).json({
>       error: err.code || 'unauthorized',
>       message: 'Authentication required',
>     });
>   } else {
>     res.status(500).json({
>       error: 'server_error',
>       message: 'Internal Server Error',
>     });
>   }
> });
>
> app.listen(port, () => {
>   console.log(`API server running at http://localhost:${port}`);
> });
> ```
>
> Ajoutez un `tsconfig.json` :
>
> ```json tsconfig.json theme={null}
> {
>   "compilerOptions": {
>     "target": "ES2020",
>     "module": "commonjs",
>     "strict": true,
>     "esModuleInterop": true,
>     "skipLibCheck": true,
>     "outDir": "./dist"
>   },
>   "include": ["*.ts"]
> }
> ```
>
> Exécutez avec : `npx ts-node server.ts`

***

## Dépannage

> **Problèmes courants et solutions**
>
> ### "Aucun jeton d'autorisation n'a été trouvé"
>
> **Problème :** L’API ne trouve pas le jeton d’accès dans la requête.
>
> **Solutions :**
>
> 1. Assurez-vous que l’en-tête `Authorization` est présent : `Authorization: Bearer YOUR_TOKEN`
> 2. Vérifiez que "Bearer" est bien indiqué avant le jeton
> 3. Vérifiez que le jeton n’est pas expiré
>
> ### "Jeton invalide" ou "jwt malformed"
>
> **Problème :** Le format du jeton n’est pas valide.
>
> **Solutions :**
>
> 1. Assurez-vous d’utiliser un **jeton d’accès**, et non un ID token
> 2. Le jeton doit être obtenu avec le paramètre `audience` de votre API
> 3. Vérifiez que le jeton est un JWT valide (il doit comporter trois parties séparées par des points)
>
> ### Valeur "iss" ou "aud" inattendue
>
> **Problème :** L’émetteur ou l’audience du jeton ne correspond pas à votre configuration.
>
> **Solutions :**
>
> 1. Décodez votre jeton sur [jwt.io](https://jwt.io)
> 2. Vérifiez que la claim `iss` correspond à `https://YOUR_AUTH0_DOMAIN/` (notez la barre oblique à la fin)
> 3. Vérifiez que la claim `aud` correspond exactement à votre `AUTH0_AUDIENCE`
> 4. Vérifiez les valeurs de votre `.env` :
>
> ```bash theme={null}
> AUTH0_DOMAIN=dev-abc123.us.auth0.com
> AUTH0_AUDIENCE=https://my-express-api.example.com
> ```
>
> ### "You must provide an issuerBaseURL" ou "audience is required"
>
> **Problème :** Les variables d’environnement ne sont pas chargées.
>
> **Solutions :**
>
> 1. Assurez-vous que le fichier `.env` existe à la racine de votre projet
> 2. Vérifiez que `dotenv` est installé : `npm install dotenv`
> 3. Ajoutez `require('dotenv').config()` tout en haut de votre fichier serveur
> 4. Vérifiez que les noms de variables correspondent exactement, y compris la casse
>
> ### 401 Unauthorized pour toutes les requêtes
>
> **Causes possibles :**
>
> * Le jeton est expiré
> * L’audience ne correspond pas
> * L’émetteur ne correspond pas
>
> **Étapes de débogage :**
>
> 1. Décodez votre jeton sur [jwt.io](https://jwt.io)
> 2. Vérifiez que la claim `exp` n’est pas expirée
> 3. Vérifiez que la claim `aud` correspond exactement à votre `AUTH0_AUDIENCE`
> 4. Vérifiez que la claim `iss` est `https://{AUTH0_DOMAIN}/`
> 5. Assurez-vous que le format de l’en-tête `Authorization` est `Bearer YOUR_TOKEN` (avec un espace)
>
> ### 403 Forbidden avec "insufficient\_scope"
>
> **Problème :** Le jeton n’a pas les scopes requis.
>
> **Solutions :**
>
> 1. Vérifiez que les scopes sont définis dans votre API Auth0 (Dashboard → **Applications** → **APIs** → **Permissions**)
> 2. Demandez les scopes au moment d’obtenir le jeton
> 3. Vérifiez que la claim `scope` du jeton inclut les scopes requis
>
> ### Erreurs CORS dans le navigateur
>
> **Problème :** Le navigateur bloque les requêtes API en raison de la politique CORS.
>
> **Solution :** Installez et configurez `cors` :
>
> ```bash theme={null}
> npm install cors
> ```
>
> ```javascript theme={null}
> const cors = require('cors');
>
> app.use(cors({
>   origin: 'http://localhost:3000',
> }));
> ```

***

## Prochaines étapes

Maintenant que vous avez une API protégée, songez à explorer :

* **[Contrôle d’accès basé sur les rôles](https://auth0.com/docs/fr-ca/manage-users/access-control/rbac.md)** - Mettez en œuvre des permissions granulaires
* **[Pratiques exemplaires en matière d’autorisation des API](https://auth0.com/docs/fr-ca/secure/tokens/access-tokens.md)** - Découvrez les pratiques exemplaires relatives aux jetons d’accès
* **[Surveillez votre API](https://auth0.com/docs/fr-ca/deploy-monitor/logs.md)** - Configurez la journalisation et la surveillance
* **[Auth0 Community](https://community.auth0.com/)** - Obtenez de l’aide auprès de la communauté

***

## Ressources

* **[express-oauth2-jwt-bearer GitHub](https://github.com/auth0/node-oauth2-jwt-bearer/tree/main/packages/express-oauth2-jwt-bearer)** - Code source et exemples
* **[Documentation d’Express.js](https://expressjs.com/)** - Pour en savoir plus sur Express
* **[Authentification de l’API Auth0](https://auth0.com/docs/fr-ca/secure/tokens/access-tokens.md)** - Comprendre les jetons d’accès
* **[JWT.io](https://jwt.io/)** - Déboguer et décoder les JWT
