jwt decode security authentication tokens

Comprendre les JWT : Comment décoder et générer des JSON Web Tokens

Un guide complet sur les JSON Web Tokens (JWT). Apprenez à décoder, vérifier et générer des jetons pour le débogage d'une authentification sécurisée.

Introduction : Qu'est-ce qu'un JSON Web Token ?

JSON Web Token (JWT) est un standard ouvert (RFC 7519) qui définit une méthode compacte et autonome pour transmettre des informations de manière sécurisée entre des parties sous forme d'objet JSON. Ces informations peuvent être vérifiées et considérées comme fiables parce qu'elles sont signées numériquement. Les JWT peuvent être signés à l'aide d'un secret (algorithme HMAC) ou d'une paire de clés publique/privée (RSA ou ECDSA).

Les JWT ont été créés pour résoudre un problème fréquent dans les systèmes distribués : comment un serveur peut-il faire confiance à une requête d'un client sans avoir besoin de consulter une session en base de données ? La réponse consiste à encoder et signer l'identité et les permissions de l'utilisateur directement dans un token que le client transporte à chaque requête.

Aujourd'hui, les JWT constituent l'épine dorsale de l'authentification et de l'autorisation modernes :

  • Single Sign-On (SSO) : Une seule connexion donne accès à plusieurs services.
  • Authentification API : Les applications mobiles et les SPA authentifient les appels API avec un Bearer token.
  • OAuth 2.0 / OpenID Connect : Les JWT sont utilisés comme access tokens et ID tokens.
  • Microservices : Les services vérifient l'identité de l'appelant sans magasin de sessions central.

Structure d'un JWT : header.payload.signature

Un JWT est une chaîne de trois parties encodées en Base64url, séparées par des points (.) :

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Partie 1 — Header (En-tête) décodé :

{
  "alg": "HS256",
  "typ": "JWT"
}

L'en-tête spécifie l'algorithme de signature (alg) et le type de token (typ).

Partie 2 — Payload (Charge utile) décodé :

{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022
}

Le payload contient les claims — des assertions sur l'entité (généralement un utilisateur) et des métadonnées supplémentaires.

Partie 3 — Signature (pour HS256) calculée ainsi :

HMACSHA256(
  base64UrlEncode(header) + "." + base64UrlEncode(payload),
  secret
)

La signature garantit que le token n'a pas été altéré. Note critique : Le payload est uniquement encodé en Base64url, pas chiffré. Toute personne possédant un JWT peut décoder et lire tous les claims.

Algorithmes de Signature : HS256, RS256 et ES256

HS256 (HMAC-SHA256) — Symétrique

Utilise un unique secret partagé pour signer et vérifier. Simple à implémenter, mais le même secret doit être connu de l'émetteur et du vérificateur.

  • Idéal pour : Applications monolithiques ou services fortement couplés partageant un secret.
  • Risque : Si le secret fuite, tous les tokens peuvent être falsifiés.

RS256 (RSA-SHA256) — Asymétrique

Utilise une clé privée pour signer et une clé publique pour vérifier. La clé privée reste secrète ; la clé publique peut être partagée librement via un endpoint JWKS.

  • Idéal pour : Systèmes distribués, microservices et scénarios où plusieurs services vérifient des tokens.
  • Taille de clé : Minimum 2048 bits pour RSA recommandé.

ES256 (ECDSA-SHA256) — Asymétrique

Utilise l'algorithme de signature numérique à courbe elliptique avec la courbe P-256. Produit des signatures plus petites que RS256 avec une sécurité équivalente.

  • Idéal pour : Environnements contraints en performances ou en bande passante.
Algorithme Type Clé Taille de signature Cas d'usage
HS256 Symétrique Secret partagé 32 octets Apps mono-service
RS256 Asymétrique Paire de clés RSA 256+ octets Systèmes distribués
ES256 Asymétrique Paire de clés EC 64 octets APIs haute performance

Claims JWT : Enregistrés, Publics et Privés

Les claims sont des assertions sur une entité (généralement un utilisateur) et des métadonnées encodées dans le payload.

Claims Enregistrés (définis par l'IANA)

Claim Nom complet Description
iss Issuer Qui a émis le token (ex : "auth.example.com")
sub Subject À qui le token se réfère (ex : un identifiant utilisateur)
aud Audience Pour qui le token est destiné (identifiant de service)
exp Expiration Horodatage Unix après lequel le token est invalide
nbf Not Before Le token ne doit pas être utilisé avant cet horodatage
iat Issued At Horodatage Unix de l'émission du token
jti JWT ID Identifiant unique pour prévenir les attaques par rejeu

Claims Publics

Définis dans le Registre des Claims JWT de l'IANA. Exemples : email, name, picture, roles.

Claims Privés

Claims personnalisés convenus entre l'émetteur et le consommateur. Utilisez des noms avec espaces de noms pour éviter les collisions :

{
  "https://example.com/tenant_id": "acme-corp",
  "https://example.com/roles": ["admin", "editor"]
}

Comment Fonctionne le Flux d'Authentification JWT

  1. Connexion de l'utilisateur : Le client envoie ses identifiants (nom d'utilisateur + mot de passe) au serveur d'authentification.
  2. Émission du token : Le serveur valide les identifiants, crée un JWT signé avec les claims appropriés et le retourne au client.
  3. Stockage du token : Le client stocke le JWT (en mémoire, dans le localStorage ou dans un cookie HttpOnly).
  4. Requêtes authentifiées : Pour chaque requête vers une ressource protégée, le client inclut le JWT dans l'en-tête Authorization :
    Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
    
  5. Vérification du token : Le serveur extrait le token, vérifie la signature, contrôle exp et accorde ou refuse l'accès selon les claims.
  6. Renouvellement du token : Lorsque l'access token expire, le client utilise un refresh token longue durée pour obtenir un nouvel access token sans se réauthentifier.
Client            Serveur Auth          Serveur de ressources
  |                    |                     |
  |-- POST /login ---->|                     |
  |<-- 200 + JWT ------|                     |
  |                    |                     |
  |-- GET /api (Authorization: Bearer JWT) ->|
  |                    |   vérifier JWT      |
  |<----------- 200 + données -------------->|

Considérations de Sécurité

Le Payload N'est PAS Chiffré

L'encodage Base64url n'est pas un chiffrement. Toute personne possédant un JWT peut immédiatement décoder et lire tous les claims. Ne jamais inclure dans un payload JWT :

  • Mots de passe ou hachages de mots de passe
  • Numéros de carte bancaire ou autres données financières
  • Informations personnelles sensibles (PII) au-delà du nécessaire
  • Clés privées ou secrets internes

Toujours Vérifier la Signature

// Node.js — bibliothèque jsonwebtoken
const jwt = require("jsonwebtoken");

try {
  const decoded = jwt.verify(token, process.env.JWT_SECRET);
  console.log(decoded.sub); // Identifiant utilisateur de confiance
} catch (err) {
  res.status(401).json({ error: "Token invalide ou expiré" });
}

Utiliser des Durées d'Expiration Courtes

Les access tokens devraient avoir des durées de vie courtes (15 minutes à 1 heure). Utilisez des refresh tokens pour les sessions longues et limiter l'impact d'un vol de token.

Toujours Utiliser HTTPS

Ne transmettez jamais des tokens sur des connexions non chiffrées. Un token intercepté est aussi dangereux qu'un mot de passe volé.

Vulnérabilités Courantes

1. Attaque par Confusion d'Algorithme (CVE-2015-9235)

Un attaquant modifie le champ alg dans l'en-tête de RS256 à HS256, puis signe le token avec la clé publique du serveur comme secret HMAC. Un serveur mal implémenté accepte ce token falsifié.

Atténuation : Spécifiez toujours l'algorithme attendu explicitement côté serveur :

jwt.verify(token, publicKey, { algorithms: ["RS256"] });

2. L'Attaque de l'Algorithme "none"

Si un serveur accepte alg: "none", un attaquant peut créer des tokens sans aucune signature.

Atténuation : Refusez explicitement les tokens avec alg: "none". Les bibliothèques modernes ont corrigé ce problème, mais les anciennes versions peuvent rester vulnérables.

3. Secrets Faibles (HS256)

Un secret HMAC court ou facile à deviner peut être cracké hors ligne par force brute avec des outils comme hashcat sur un token capturé.

Atténuation : Utilisez un secret aléatoire cryptographiquement sûr d'au moins 256 bits :

openssl rand -hex 32

4. Validation des Claims Absente

Ne pas valider iss, aud ou nbf permet la réutilisation de tokens entre services ou leur utilisation avant la fenêtre valide.

5. Stockage Insécurisé des Tokens

localStorage est accessible par tout JavaScript de la page, rendant les tokens vulnérables aux attaques XSS. Préférez les cookies HttpOnly pour les tokens sensibles.

JWT vs Tokens de Session : Sans État vs Avec État

Caractéristique JWT (Sans état) Token de session (Avec état)
Stockage Côté client Côté serveur (BD ou cache)
Scalabilité Excellente — aucune requête serveur Nécessite un magasin de sessions partagé
Révocation Difficile — valide jusqu'à exp Facile — supprimer de la base de données
Taille du token Plus grand par requête Petit token opaque, données sur le serveur
Microservices Idéal — vérification indépendante Nécessite une infrastructure partagée
Visibilité Lisible par quiconque possède le token Données uniquement côté serveur

Choisissez JWT pour les systèmes distribués, les APIs REST sans état ou les applications mobiles. Choisissez les sessions lorsque vous avez besoin d'une révocation immédiate (ex : "déconnexion de tous les appareils").

Le Défi de la Révocation

Comme les JWT sont autonomes, vous ne pouvez pas annuler un token avant son expiration sans infrastructure supplémentaire :

  • Expiration courte + refresh tokens : Les access tokens expirent rapidement ; révoquez les refresh tokens en BD.
  • Liste noire de tokens : Stockez les jti révoqués dans Redis (réintroduit une certaine gestion d'état).
  • Rotation des secrets : Faites tourner le secret de signature pour invalider tous les tokens (impacte tous les utilisateurs).

OAuth 2.0 et OpenID Connect

OAuth 2.0

OAuth 2.0 est un framework d'autorisation qui n'impose pas de format de token spécifique. Mais les JWT sont largement utilisés comme access tokens OAuth car ils sont autonomes et peuvent porter des scopes d'autorisation :

{
  "iss": "https://auth.example.com",
  "sub": "user_123",
  "aud": "https://api.example.com",
  "scope": "read:profile write:posts",
  "exp": 1893456000
}

OpenID Connect (OIDC)

OpenID Connect est une couche d'identité construite au-dessus d'OAuth 2.0. Il introduit l'ID Token, qui est toujours un JWT contenant des claims d'identité sur l'utilisateur authentifié :

{
  "iss": "https://accounts.google.com",
  "sub": "110169484474386276334",
  "aud": "my-client-id.apps.googleusercontent.com",
  "email": "[email protected]",
  "name": "Jane Doe",
  "exp": 1893456000,
  "iat": 1893452400
}

OIDC définit également l'endpoint JWKS (/.well-known/jwks.json), où le serveur d'autorisation publie ses clés publiques. N'importe quel service peut récupérer ces clés pour vérifier des tokens sans échange de clés préalable.

Bonnes Pratiques

  1. Utilisez des algorithmes asymétriques (RS256/ES256) pour les systèmes publics — protégez la clé privée de signature tout en permettant à quiconque de vérifier avec la clé publique.
  2. Définissez des valeurs exp courtes pour les access tokens — 15 minutes est une valeur par défaut courante et sûre.
  3. Faites toujours tourner les refresh tokens — émettez-en un nouveau à chaque utilisation et invalidez l'ancien.
  4. Validez tous les claims pertinents — vérifiez au minimum iss, aud, exp et nbf.
  5. Spécifiez l'algorithme attendu explicitement — ne faites jamais confiance uniquement au champ alg dans l'en-tête du token.
  6. Ne mettez jamais de données sensibles dans le payload — il est encodé, pas chiffré.
  7. Utilisez toujours HTTPS — ne transmettez jamais des tokens sur des connexions non chiffrées.
  8. Stockez les tokens en toute sécurité — préférez les cookies HttpOnly, Secure, SameSite=Strict au localStorage.
  9. Implémentez une stratégie de révocation des tokens — utilisez une liste noire ou des tokens de courte durée avec rotation des refresh tokens.
  10. Maintenez les bibliothèques JWT à jour — les nouvelles versions incluent des correctifs de sécurité.

Foire Aux Questions (FAQ)

Q : Puis-je déchiffrer le payload d'un JWT ? R : Le payload d'un JWT est encodé en Base64url, pas chiffré — aucune clé n'est nécessaire pour le lire. Si vous avez besoin de confidentialité, utilisez JWE (JSON Web Encryption, RFC 7516), qui chiffre réellement le payload.

Q : Quelle est la différence entre decode et verify ? R : decode décode simplement les parties en Base64url et retourne le JSON sans aucune vérification de sécurité. verify valide également la signature avec votre clé et contrôle les claims temporels comme exp. Utilisez toujours verify en production.

Q : Comment gérer le renouvellement de tokens de manière sécurisée ? R : Émettez un access token de courte durée (15–60 min) et un refresh token de longue durée (jours à semaines). Stockez les refresh tokens côté serveur pour pouvoir les révoquer. Lorsque l'access token expire, le client envoie le refresh token à un endpoint dédié pour obtenir un nouvel access token.

Q : Puis-je utiliser JWT à la fois pour l'authentification et l'autorisation ? R : Oui. Incluez des claims d'identité (qui est l'utilisateur) et des claims d'autorisation (ce qu'il peut faire, ex : roles, scope) dans le même token. Gardez la taille du payload raisonnable.

Q : Que se passe-t-il si mon secret JWT est compromis ? R : Un attaquant peut falsifier des tokens valides pour n'importe quel utilisateur. Faites tourner le secret immédiatement (cela invalide tous les tokens existants), enquêtez sur la source de la compromission et forcez tous les utilisateurs à se réauthentifier.

Q : Dois-je utiliser HS256 ou RS256 ? R : Utilisez RS256 (ou ES256) lorsque plusieurs services vérifient des tokens ou lorsque le vérificateur n'est pas entièrement de confiance. Utilisez HS256 uniquement lorsque le même service émet et vérifie des tokens dans une limite de déploiement strictement contrôlée.

Q : Quelle peut être la taille maximale d'un JWT ? R : Gardez les JWT sous 4 Ko pour éviter les limites de taille des en-têtes HTTP et les problèmes de performances. N'intégrez pas de grandes structures de données dans le payload ; référencez-les plutôt par ID.