La plupart des bugs JWT en TypeScript ne sont pas dans le token — ils sont dans la configuration de vérification. Une contrainte d'algorithme manquante, un claim d'émetteur non vérifié ou un secret à courte durée de vie peuvent miner silencieusement l'authentification d'une manière qui ne se révèle qu'en production. Ce guide parcourt chaque dimension de la justesse de configuration JWT en TypeScript : algorithmes, validation des claims, hygiène des secrets, gestion de l'expiration et les outils navigateur qui accélèrent le débogage.
Ce que couvre la validation de configuration JWT
Un JSON Web Token (JWT) est une chaîne compacte et compatible URL composée de trois parties encodées en Base64URL séparées par des points : un en-tête déclarant l'algorithme et le type de token, un payload portant les claims et une signature qui les lie. Valider un JWT signifie confirmer que les trois parties sont intactes et que les claims répondent aux exigences de votre application — pas seulement que la signature est mathématiquement correcte.
Les deux couches de la validation JWT
La validation cryptographique confirme la signature : le serveur vérifie que le token a été signé avec la clé attendue et n'a pas été altéré. La validation de configuration va plus loin : elle vérifie que le token a été émis par la bonne autorité, qu'il est destiné à ce service précis, qu'il n'a pas expiré et qu'il porte les claims personnalisés attendus. La plupart des vulnérabilités de sécurité JWT viennent d'une validation de configuration incomplète, pas d'une cryptographie défaillante.
- Algorithme (`alg`) — doit correspondre exactement à la configuration de votre serveur ; ne le déduisez jamais de l'en-tête du token
- Expiration (`exp`) — le token ne doit pas avoir dépassé son horodatage d'expiration, en tenant compte de la tolérance d'horloge
- Pas-avant (`nbf`) — le token ne doit pas être utilisé avant sa première heure valide
- Émetteur (`iss`) — le token doit provenir de votre service d'authentification de confiance
- Audience (`aud`) — le token doit être destiné à cette API ou ce service précis
- Claims personnalisés — rôle, scope, ID de tenant ou tout champ spécifique à l'application dont dépend votre logique
Note
Contrôles de l'algorithme et de la configuration des clés
La configuration de l'algorithme est le réglage le plus critique pour la sécurité dans la vérification JWT. Se tromper ouvre la voie à une classe d'attaques qui contourne entièrement l'authentification. Les bibliothèques JWT de TypeScript vous donnent les outils pour l'imposer correctement — mais seulement si vous les utilisez explicitement.
HS256 vs RS256 — choisir le bon algorithme
| Propriété | HS256 (symétrique) | RS256 (asymétrique) |
|---|---|---|
| Type de clé | Secret partagé (même clé pour signer + vérifier) | Paire de clés RSA (privée pour signer, publique pour vérifier) |
| Distribution des clés | Chaque vérificateur détient le secret | Seul l'émetteur détient la clé privée |
| Sécurité multi-services | ✗ Risqué — tous les vérificateurs peuvent forger des tokens | ✓ Les vérificateurs ne détiennent que la clé publique |
| Prise en charge OIDC / JWKS | ✗ Non applicable | ✓ Clés publiques servies via un endpoint JWKS |
| Performance | ✓ Rapide (HMAC) | ✗ Plus lent (calcul RSA) |
| Idéal pour | Outils internes, APIs mono-service | APIs de production, systèmes distribués, OIDC |
L'attaque de confusion d'algorithme — et comment la prévenir
La confusion d'algorithme survient quand un serveur lit le champ `alg` de l'en-tête JWT pour décider comment vérifier le token, au lieu d'imposer l'algorithme depuis sa propre configuration. Un attaquant modifie l'en-tête pour changer `RS256` en `HS256`, puis signe le token avec la clé publique du serveur utilisée comme secret HMAC. Un serveur mal configuré l'accepte comme valide. Le correctif tient en une ligne de code — mais elle doit être présente.
// ✗ Vulnerable - algorithm inferred from token header
jwt.verify(token, publicKey);
// ✓ Correct - algorithm enforced from server configuration
jwt.verify(token, publicKey, { algorithms: ['RS256'] });Warning
Validation de la force de clé pour HS256
Avec HS256, le secret doit faire au moins 256 bits (32 octets) pour correspondre à la taille de sortie de SHA-256. Les secrets courts — moins de 32 caractères, mots du dictionnaire ou chaînes statiques comme `"secret"` ou `"development"` — se cassent trivialement par force brute avec des outils comme `hashcat` ou `jwt_tool`. Générez les secrets avec une source aléatoire cryptographiquement sûre : `crypto.randomBytes(32).toString('hex')` dans Node.js produit une chaîne hexadécimale de 64 caractères qui satisfait l'exigence minimale d'entropie.
Valider les claims JWT standards en TypeScript
La spécification JWT définit un ensemble de claims enregistrés standards que toute implémentation devrait comprendre. La bibliothèque `jsonwebtoken` en valide plusieurs automatiquement quand vous passez les bonnes options — mais le mot clé est « quand vous les passez ». Sans configuration explicite, la plupart des vérifications de claims sont silencieusement ignorées.
Les claims exp, nbf et iat
Le claim exp (expiration) est un horodatage Unix après lequel le token n'est plus valide. La bibliothèque jsonwebtoken vérifie exp par défaut pendant jwt.verify(). Cependant, la dérive d'horloge entre l'émetteur du token et le vérificateur peut faire rejeter des tokens valides — source fréquente d'erreurs « token expiré » dans les systèmes distribués où les horloges des serveurs dérivent de quelques secondes. Passez clockTolerance pour autoriser une petite fenêtre : fixer clockTolerance à 30 accepte les tokens jusqu'à 30 secondes après leur valeur exp.
interface JwtPayload {
sub: string;
iss: string;
aud: string;
exp: number;
iat: number;
role: 'admin' | 'user';
}
const payload = jwt.verify(token, publicKey, {
algorithms: ['RS256'],
issuer: 'https://auth.example.com',
audience: 'api.example.com',
clockTolerance: 30, // seconds of clock skew to tolerate
}) as JwtPayload;Les claims iss et aud
Le claim `iss` (émetteur) identifie l'origine du token. Le claim `aud` (audience) identifie le destinataire prévu. Tous deux sont optionnels dans la spécification JWT mais critiques en pratique. Sans validation de `iss`, tout service capable de produire des tokens valides avec votre clé de signature peut s'authentifier auprès de votre API. Sans validation de `aud`, un token émis pour votre application mobile peut être rejoué contre votre API d'administration. Passez les deux comme options à `jwt.verify()` pour que la bibliothèque les impose comme exigences strictes plutôt que comme champs informatifs.
Tip
Implémenter la validation JWT en TypeScript
Une fonction complète de vérification JWT en TypeScript gère la validation cryptographique, la validation des claims et la classification des erreurs au même endroit. Voici comment la structurer — avec les quatre étapes correspondant au schéma HowTo.
Vérifiez que l'algorithme correspond à votre type de clé
Avant d'écrire du code de vérification, confirmez votre combinaison algorithme/clé. RS256 exige une clé privée RSA pour signer et la clé publique correspondante pour vérifier. HS256 exige le même secret partagé des deux côtés. Les confondre provoque des exceptions à l'exécution difficiles à diagnostiquer. Stockez votre clé publique ou votre secret partagé dans des variables d'environnement — ne les incorporez jamais dans les fichiers sources.
Validez explicitement les claims exp et nbf
Fixez toujours `clockTolerance` pour gérer les petites dérives d'horloge entre services. Une valeur de 30 secondes est un défaut raisonnable pour la plupart des systèmes distribués. En déboguant `TokenExpiredError` en production, journalisez `payload.exp * 1000` et `Date.now()` ensemble — cela montre exactement de combien de millisecondes le token a dépassé l'expiration, distinguant une vraie expiration d'un problème de synchronisation d'horloge entre votre service d'authentification et le serveur API.
Contrôlez les claims iss et aud contre les valeurs attendues
Passez les options `issuer` et `audience` à `jwt.verify()` pour que la bibliothèque rejette les tokens aux valeurs non correspondantes avant l'exécution de votre code applicatif. Si votre système a plusieurs audiences valides (par exemple `api.example.com` et `admin.example.com`), passez un tableau : `audience: ['api.example.com', 'admin.example.com']`. La bibliothèque accepte le token si le claim `aud` correspond à n'importe quelle entrée du tableau.
Testez votre configuration avec le Décodeur JWT
Avant d'exécuter votre suite de tests TypeScript, collez un token d'exemple de votre environnement de développement ou de recette dans le Décodeur et Validateur JWT. Confirmez visuellement que chaque claim — `alg`, `exp`, `iss`, `aud` et vos claims personnalisés — correspond aux options de votre `jwt.verify()`. Cette vérification d'une minute attrape les divergences entre ce que contient le token et ce qu'attend votre code, avant de passer du temps à déboguer dans un environnement de test.
Décodeur et Validateur JWT
Décodez les tokens JWT et inspectez tous les claims, champs d'en-tête et problèmes de sécurité courants instantanément dans votre navigateur — sans inscription, sans envoi au serveur.
Erreurs de configuration JWT courantes
Voici les erreurs de configuration les plus fréquentes dans les implémentations JWT TypeScript. Chacune est silencieuse au démarrage et ne se manifeste que comme un échec d'authentification ou un incident de sécurité en production.
Utiliser `jwt.decode()` au lieu de `jwt.verify()`
La fonction `jwt.decode()` extrait le payload sans vérifier la signature. Elle sert à inspecter un token en qui vous avez déjà confiance — par exemple extraire un ID utilisateur d'un token déjà validé par le middleware. Ce n'est pas un substitut à `jwt.verify()`. Un code qui utilise `jwt.decode()` pour obtenir des claims puis prend des décisions d'autorisation à partir de ces claims accepte des tokens non vérifiés. C'est une contournement complet de l'authentification.
Ignorer le type d'erreur dans les blocs catch
La bibliothèque `jsonwebtoken` lève trois types d'erreurs distincts : `JsonWebTokenError` (token malformé ou signature invalide), `TokenExpiredError` (au-delà du claim `exp`) et `NotBeforeError` (avant le claim `nbf`). Capturer toutes les erreurs comme un `Error` générique et renvoyer `401 Unauthorized` pour tous les cas perd des informations de diagnostic. Traitez chaque type séparément et renvoyez des messages spécifiques — « token expiré » contre « token invalide » — pour que les clients et les systèmes de surveillance distinguent les problèmes de configuration des vraies tentatives d'attaque.
Ne pas faire tourner les secrets ou paires de clés
Les secrets de signature à longue durée de vie accumulent le risque avec le temps. Un secret jamais renouvelé signifie que chaque token émis avec lui reste valide si le secret est compromis. Implémentez un champ d'ID de clé (`kid`) dans votre en-tête JWT pour que le vérificateur puisse retrouver la bonne clé publique depuis un endpoint JWKS. Ce modèle permet la rotation des clés sans invalider les tokens signés par la clé précédente — chaque token porte une référence à la clé spécifique qui l'a signé. L'Inspecteur de JWK aide à valider la sortie d'un endpoint JWKS et à détecter du matériel de clé privée qui ne devrait pas être exposé publiquement.
Warning
Accepter l'algorithme `none`
L'algorithme `none` produit un JWT non signé — tout payload de structure valide passe la vérification. Les premières versions des bibliothèques JWT acceptaient `none` par défaut. Les bibliothèques modernes le rejettent, mais seulement quand vous spécifiez explicitement les algorithmes autorisés dans les options de vérification. Incluez toujours `algorithms: ['RS256']` (ou votre algorithme spécifique) pour rendre le rejet de `none` explicite et résilient aux changements de version de la bibliothèque.
Déboguer les problèmes JWT avec des outils navigateur
Écrire un test pour reproduire une erreur JWT est souvent plus lent que d'inspecter directement le token. Les outils navigateur vous permettent d'examiner les claims d'un token, son état d'expiration et sa structure de clés en quelques secondes — sans environnement local, sans exécuter de code et sans envoyer de données sensibles à un service tiers.
Décoder et inspecter les claims
Le Décodeur et Validateur JWT décode l'en-tête et le payload de n'importe quelle chaîne JWT et présente tous les claims dans un format structuré et lisible. Il contrôle les problèmes de sécurité courants — `exp` manquant, algorithme faible, `aud` manquant — et les signale avec des diagnostics clairs. Collez n'importe quel token de vos environnements de développement, de recette ou de production et confirmez en dix secondes si les claims correspondent à ce qu'attend votre appel `jwt.verify()`.
Diagnostiquer les problèmes d'expiration
La Calculatrice de Compte à Rebours d'Expiration JWT lit le claim `exp` de n'importe quel token et affiche la durée de vie restante exacte ou le temps écoulé depuis l'expiration en UTC comme en heure locale. Quand un utilisateur signale « token expiré » mais que vos logs montrent que le token devrait encore être valide, collez-le dans la calculatrice. La comparaison d'horodatages à la milliseconde révèle si le problème est une vraie expiration, une dérive d'horloge entre services ou une valeur `exp` stockée en millisecondes au lieu de secondes — un bug de facteur 1000 étonnamment courant.
Inspecter les jeux de clés JWKS
Pour valider des tokens provenant d'un fournisseur OIDC ou de tout service publiant un endpoint JWKS, l'Inspecteur de JWK analyse et valide la structure du jeu de clés. Il vérifie que chaque clé possède les champs requis (`kty`, `use`, `alg`, `kid`), valide le type de clé et la courbe pour les clés EC, et signale tout matériel de clé privée qui ne devrait pas être exposé publiquement. Collez le JSON de votre endpoint JWKS directement dans l'outil ou fournissez l'URL pour un fetch.
Calculatrice de Compte à Rebours d'Expiration JWT
Calculez le compte à rebours exact d'expiration JWT à partir du claim exp — voyez le temps restant ou le temps écoulé depuis l'expiration en UTC et en heure locale, sans code.
Bonnes pratiques de validation JWT
Une fonction de vérification JWT correctement configurée est nécessaire mais pas suffisante pour une authentification sécurisée. Ces pratiques complètent le tableau pour les services TypeScript de production.
Utilisez une interface de payload typée
Définissez une interface TypeScript pour votre payload JWT et convertissez le résultat de vérification vers elle. Cela vous donne une sécurité à la compilation sur les noms de claims et les types de valeurs — un nom de claim mal orthographié (`userId` contre `user_id`) devient une erreur TypeScript plutôt qu'un `undefined` silencieux à l'exécution. Gardez l'interface dans un module de types partagé pour qu'elle reste cohérente entre tous les services qui vérifient le même format de token.
Durées de vie courtes des tokens avec refresh tokens
Les tokens d'accès devraient avoir des durées de vie courtes — 15 minutes à 1 heure pour la plupart des APIs. Les tokens d'accès longue durée (jours, semaines) élargissent la fenêtre pendant laquelle un token compromis peut être utilisé. Utilisez un flux séparé de refresh token à expiration longue pour la persistance de session. Le refresh token tourne à chaque utilisation, et les listes de révocation ne sont nécessaires que pour les refresh tokens — pas les tokens d'accès — quand les durées restent courtes.
Centralisez la logique de vérification
Écrivez la vérification JWT à un seul endroit — une fonction de middleware ou une utilité partagée — et utilisez-la partout. La logique de vérification dupliquée invite à la dérive de configuration : un endpoint vérifie `aud`, un autre oublie, et l'incohérence est exploitée avant que quiconque ne s'en aperçoive. Le middleware Express, les guards NestJS et les gestionnaires de routes Next.js offrent tous des modèles propres pour centraliser les contrôles d'authentification. Placez vos options `algorithms`, `issuer` et `audience` dans un unique objet de configuration importé dans tout le code.
Configurez la vérification une fois, imitez-la partout. La seule option JWT qui devrait différer entre endpoints est l'audience attendue.
Tip
Key takeaways
- Passez toujours `algorithms: ['RS256']` (ou votre algorithme spécifique) explicitement à `jwt.verify()` — ne laissez jamais la bibliothèque le déduire de l'en-tête du token.
- Validez les claims `iss` et `aud` à chaque appel de vérification ; les omettre permet à des tokens d'autres services de s'authentifier auprès de votre API.
- Utilisez `clockTolerance` pour gérer la dérive d'horloge entre services distribués, et journalisez les horodatages `exp` aux côtés de `Date.now()` lors du débogage des erreurs d'expiration.
- N'utilisez jamais `jwt.decode()` pour des décisions d'autorisation — il saute entièrement la vérification de signature et accepte tout payload de token.
- Le Décodeur et Validateur JWT vous permet d'inspecter tous les claims et de signaler les problèmes de configuration en quelques secondes, sans écrire ni exécuter de code.
- RS256 est préféré à HS256 pour les APIs de production — il élimine le risque de distribution de secret partagé et prend en charge la rotation de clés basée sur JWKS.
- Gardez les durées de vie des tokens d'accès courtes (15-60 minutes) et centralisez toute la logique de vérification dans un seul middleware ou utilitaire pour prévenir la dérive de configuration.