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 de votre API avec Auth0 en quelques minutes grâce aux agent skills.Installation :
npx skills add auth0/agent-skills --skill auth0-quickstart --skill auth0-express-api
Ensuite, demandez à votre assistant IA :
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 les points de terminaison de votre API avec la validation des jetons. Documentation complète sur les agent skills →
Prérequis : Avant de commencer, assurez-vous d’avoir installé les éléments suivants :
  • Node.js 18 LTS ou une version plus récente (prend en charge ^18.12.0 || ^20.2.0 || ^22.1.0 || ^24.0.0)
  • npm 8+ ou yarn 1.22+ ou pnpm 8+
Vérifiez l’installation : node --version && npm --versionCompatibilité des versions d’Express : Ce guide de démarrage rapide fonctionne avec Express 4.x et Express 5.x.

Pour commencer

Ce guide de démarrage rapide montre comment protéger les points de terminaison d’une API Express.js à l’aide de jetons d’accès JWT. Vous créerez une API sécurisée qui valide les jetons d’accès Auth0, protège les routes et met en place une autorisation basée sur les scopes.
1

Créer un nouveau projet

Créez un nouveau répertoire pour votre API Express et initialisez un projet Node.js.
mkdir auth0-express-api && cd auth0-express-api
Initialisez le projet
npm init -y
Créer la structure du projet
touch server.js .env
2

Installez le SDK express-oauth2-jwt-bearer

Installez les dépendances requises
npm install express express-oauth2-jwt-bearer dotenv
Ajoutez des scripts de démarrage à votre package.json :
package.json
{
  "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 locataire 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 Auth0 Dashboard :
Exécutez la commande suivante à la racine de votre projet pour créer une API Auth0 :
# Installer Auth0 CLI (si ce n’est pas déjà fait)
brew tap auth0/auth0-cli && brew install auth0

# Créer l’API Auth0
auth0 apis create \
  --name "My Express API" \
  --identifier https://my-express-api.example.com
Cette commande permet de :
  1. Vérifier si vous êtes authentifié (et vous demander de vous connecter au besoin)
  2. Créer une API Auth0 avec l’identifiant spécifié
  3. Afficher les détails de l’API, y compris le domaine et l’identifiant
Après la création, copiez les valeurs Identifier et Domain, puis créez votre fichier .env :
.env
AUTH0_DOMAIN=YOUR_AUTH0_DOMAIN
AUTH0_AUDIENCE=YOUR_API_IDENTIFIER
Remplacez YOUR_AUTH0_DOMAIN par le domaine de votre locataire 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).
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 du JWT :
server.js
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 intergiciel 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 entrants
  • Met checkJwt à votre disposition pour protéger des routes individuelles
5

Créer des routes API

Ajoutez des routes publiques et protégées dans votre server.js :
server.js
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 jeton d'accès 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 autorisations précises dans le JWT
  • req.auth.payload contient les claims décodées du JWT pour les requêtes authentifiées
  • La claim sub contient l’identifiant unique de l’utilisateur
6

Démarrez votre API

Démarrez le serveur de développement :
npm run dev
Votre API s’exécute maintenant à l’adresse http://localhost:3001.
L’option --watch de Node.js 18+ redémarre automatiquement le serveur lorsque les fichiers sont modifiés.
7

Testez votre API

Testez le point de terminaison public (aucune authentification n’est requise) :
curl http://localhost:3001/api/public
Vous devriez voir :
{
  "message": "Hello from a public endpoint! You don't need to be authenticated to see this.",
  "timestamp": "2024-01-15T10:30:00.000Z"
}
Testez le point de terminaison protégé sans jeton (devrait échouer) :
curl http://localhost:3001/api/private
Vous devriez voir une erreur 401 Non autorisé :
{
  "error": "unauthorized",
  "message": "Authentication required"
}
Pour effectuer un test avec un jeton valide :
  1. Accédez à Auth0 DashboardApplicationsAPIs
  2. Sélectionnez votre API → onglet Test
  3. Copiez le jeton d’accès généré
Testez votre point de terminaison protégé :
curl http://localhost:3001/api/private \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
Vous devriez voir :
{
  "message": "Hello from a protected endpoint! You successfully authenticated.",
  "user": "auth0|abc123...",
  "timestamp": "2024-01-15T10:30:00.000Z"
}
Point de contrôleVous 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 par rapport à votre domaine Auth0 et à l’audience
  4. Fournit des informations sur l’utilisateur à partir des claims du jeton via req.auth.payload

Utilisation avancée

Les scopes permettent un contrôle d’accès précis. Vous pouvez exiger des scopes spécifiques pour différents points de terminaison.Configurer les scopes dans Auth0 :
  1. Dans le Auth0 Dashboard, accédez à ApplicationsAPIs → Votre API
  2. Accédez à l’onglet Permissions
  3. Ajoutez des permissions comme read:messages, write:messages, admin:access
Protéger les routes avec des scopes :
server.js
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,
  });
});
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 scopes appropriés lorsqu’elle obtient un jeton d’accès.
En plus des scopes, vous pouvez valider des claims personnalisées dans le payload JWT :
server.js
const { auth, claimEquals, claimIncludes, claimCheck } = require('express-oauth2-jwt-bearer');

// Exige une valeur de claim exacte
app.get('/api/org/:orgId',
  checkJwt,
  claimEquals('org_id', 'org_123'),
  (req, res) => {
    res.json({ message: 'Organization access granted' });
  }
);

// Exige que le claim inclut 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' });
  }
);
Les claims personnalisées doivent utiliser des URL dans un espace de noms (par exemple, https://myapp.com/roles), sauf s’il s’agit de claims OIDC standard. En savoir plus sur les claims personnalisées.
Autorisez à la fois l’accès authentifié et l’accès anonyme à une même route :
server.js
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,
    });
  }
});
Activez CORS pour autoriser les requêtes provenant d’applications Web :
npm install cors
server.js
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 :
server.js
app.use(cors({
  origin: [
    'https://myapp.com',
    'https://www.myapp.com'
  ],
  credentials: true,
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
}));
Ajoutez une gestion complète des erreurs d’authentification :
server.js
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);
});
Pour les projets TypeScript, installez les définitions de type et configurez votre projet :
npm install -D typescript @types/express @types/node
Créez server.ts :
server.ts
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 :
tsconfig.json
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "outDir": "./dist"
  },
  "include": ["*.ts"]
}
Exécutez la commande suivante : npx ts-node server.ts

Dépannage

« 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 » figure bien avant le jeton
  3. Vérifiez que le jeton n’est pas expiré

« Jeton invalide » ou « jwt malformed »

Problème : Le format du jeton est invalide.Solutions :
  1. Assurez-vous d’utiliser un jeton d’accès, et non un jeton d’identité
  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 correspondent pas à votre configuration.Solutions :
  1. Décodez votre jeton sur 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 :
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 des variables correspondent exactement (respect de la casse)

401 Non autorisé sur 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
  2. Vérifiez que la claim exp n’est pas échue
  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 l’en-tête Authorization est au format Bearer YOUR_TOKEN (avec un espace)

403 Interdit 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 (Auth0 Dashboard → ApplicationsAPIsPermissions)
  2. Demandez les scopes lors de l’obtention du 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 stratégie CORS.Solution : Installez et configurez cors :
npm install cors
const cors = require('cors');

app.use(cors({
  origin: 'http://localhost:3000',
}));

Prochaines étapes

Maintenant que vous avez une API protégée, pensez à explorer ce qui suit :

Ressources