Un JWT (JSON Web Token), c’est trois sections encodées en Base64url réunies par des points. Décoder un token pour lire ses claims demande un seul appel de fonction et aucune clé secrète —— c’est précisément pour ça que le payload d’un JWT n’est pas un endroit sûr pour des données sensibles. Ce guide explique ce qu’est un JWT, comment décoder chaque partie, et la différence critique entre décoder et vérifier un token.
Qu’est-ce qu’un JWT ?
Un JWT est un token compact et URL-safe utilisé pour transporter des claims —— typiquement l’identité et les permissions d’un utilisateur —— entre parties. Il est standardisé dans la RFC 7519. Un token ressemble à ceci :
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0IiwibmFtZSI6IkFkYSJ9.dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXkLes deux points le séparent en trois parties : header, payload et signature.
Les trois parties
- Header —— un petit objet JSON décrivant l’algorithme de signature, par ex.
{"alg":"HS256","typ":"JWT"}. - Payload —— un objet JSON contenant des claims comme
sub(subject),exp(expiration) et n’importe quel champ personnalisé. - Signature —— une signature cryptographique sur le header et le payload, utilisée pour détecter toute manipulation. Non lisible par un humain et pas du JSON.
Header et payload sont du JSON encodé en Base64url. La signature est produite par JWS (RFC 7515).
Comment décoder un JWT en JavaScript
Coupez sur les points et décodez Base64url les deux premières parties. Notez que JWT utilise Base64url (avec - et _ à la place de + et /, sans padding), il faut donc convertir avant de décoder :
function decodeJwt(token) {
const [headerB64, payloadB64] = token.split('.');
const decode = (b64url) => {
const b64 = b64url.replace(/-/g, '+').replace(/_/g, '/');
const json = atob(b64);
return JSON.parse(json);
};
return { header: decode(headerB64), payload: decode(payloadB64) };
} Pour une sécurité Unicode totale, décodez le Base64 en octets et passez-les par TextDecoder plutôt que d’utiliser atob seul.
Comment décoder un JWT en Python
import base64, json
def decode_jwt(token):
header_b64, payload_b64, _sig = token.split('.')
def decode(part):
padded = part + '=' * (-len(part) % 4)
return json.loads(base64.urlsafe_b64decode(padded))
return decode(header_b64), decode(payload_b64)Décoder n’est pas vérifier
C’est le point le plus important à propos des JWT. N’importe qui peut décoder un token et lire son payload —— aucune clé requise. Décoder vous dit ce que le token affirme ; ça ne vous dit pas si ces claims sont dignes de confiance.
Pour faire confiance à un token, vous devez vérifier la signature contre la clé secrète ou publique du serveur, à l’aide d’une bibliothèque éprouvée —— n’implémentez jamais la vôtre :
import jwt from 'jsonwebtoken';
// Vérifie la signature ET l’expiration ; lève si invalide
const claims = jwt.verify(token, process.env.JWT_SECRET);
// jwt.decode(token) —— NE vérifie PAS ; inspection uniquementLa vérification côté serveur, c’est ce qui fait d’un JWT une credential. Traiter un payload décodé comme digne de confiance sans vérifier la signature est un bug d’authentification classique.
Le payload d’un JWT n’est pas chiffré
Comme le payload n’est que du JSON encodé en Base64url, il offre zéro confidentialité. C’est le même malentendu que celui couvert dans Base64 n’est pas du chiffrement : l’encodage peut être inversé par n’importe qui.
Ne mettez jamais de mots de passe, de numéros de carte complets ou de données personnelles sensibles dans un payload JWT. Si vous avez vraiment besoin d’un token chiffré, utilisez JWE (JSON Web Encryption, RFC 7516) —— un standard distinct et bien moins courant. Et évitez de coller de vrais tokens dans des décodeurs en ligne peu fiables ; voir pourquoi vous ne devriez pas coller du JSON sensible dans des outils en ligne.
Ordre de validation : signature d’abord, claims ensuite
Quand vous vérifiez un token en production, l’ordre importe. Une checklist sûre :
- Liste blanche d’algorithmes —— rejetez tout ce qui sort de votre ensemble attendu (par ex.
['RS256']). N’acceptez jamaisnone. - Signature —— vérifiez avec la bonne clé (cherchez-la via
kiddans votre JWKS). exp—— le token ne doit pas être expiré.nbf(not-before) —— il ne doit pas être utilisé trop tôt.iat—— sanity-check que l’émission n’est pas absurdement dans le futur (tolérer la dérive d’horloge).iss—— l’émetteur doit correspondre à l’autorité de confiance que vous attendez.aud—— l’audience doit inclure votre service.
La plupart des bibliothèques JWT font 1–4 par défaut et exigent un opt-in pour 6–7. Tant que iss et aud ne sont pas vérifiés, un token valide pour un autre service de votre écosystème pourrait être rejoué contre le vôtre.
Claims standards courants
| Claim | Signification |
|---|---|
iss | Issuer —— qui a créé le token |
sub | Subject —— de qui le token parle (souvent un ID utilisateur) |
aud | Audience —— à qui le token est destiné |
exp | Expiration —— timestamp Unix après lequel le token est invalide |
iat | Issued-at —— timestamp Unix de la création |
nbf | Not-before —— le token n’est pas valide avant ce moment |
L’en-tête kid et le piège alg: none
Deux champs d’en-tête reviennent assez souvent dans les vrais JWT pour mériter d’être reconnus au premier coup d’œil :
kid(key ID) —— un indice qui dit au vérificateur quelle clé d’un set (JWKS) a signé ce token. Il vit dans le header pour que le vérificateur puisse choisir la bonne clé avant de contrôler la signature. Traitezkidcomme une entrée non fiable : cherchez-le dans une liste blanche figée (ou un JWKS récupéré), ne l’utilisez jamais comme chemin de fichier, paramètre SQL ou URL.alg: "none"—— un algorithme légal mais historiquement dangereux qui signifie « pas de signature ». Les décodeurs le décodent volontiers, et un vérificateur trop permissif peut l’accepter, transformant n’importe quel payload forgé en token « valide ». Rejetezalg: noneexplicitement et configurez votre bibliothèque avec le ou les algorithme(s) exact(s) attendus (par ex.['RS256']) plutôt que de vous fier à ce que le header du token déclare.
Décodez un JWT dans votre navigateur
Pour inspecter rapidement les claims d’un token, collez n’importe laquelle des sections Base64url dans le décodeur Base64 de fixjson —— il décode vers le JSON sous-jacent localement, sans rien envoyer à un serveur. Pour des tokens non sensibles, vous pouvez aussi utiliser un debugger dédié, mais pour quoi que ce soit avec de vraies données utilisateur, un outil local-first est le choix sûr.
Questions fréquentes
Comment décoder un JWT ?
Coupez le token sur ses points et décodez Base64url les deux premières parties (header et payload) en JSON. La troisième est la signature et n’est pas lisible par un humain. Aucune clé n’est nécessaire pour décoder.
Décoder un JWT, est-ce la même chose que le vérifier ?
Non. Décoder ne fait que lire les claims ; n’importe qui peut le faire. Vérifier contrôle la signature contre une clé secrète ou publique pour confirmer que le token est authentique et n’a pas été manipulé. Vérifiez toujours côté serveur avant de faire confiance à un token.
N’importe qui peut-il lire les données d’un JWT ?
Oui. Le payload est encodé en Base64url, pas chiffré —— c’est du texte clair pour quiconque possède le token. Ne mettez jamais de secrets dans un payload JWT. Voir Base64 n’est pas du chiffrement.
Quelle est la différence entre JWT, JWS et JWE ?
Un JWT signé utilise JWS (RFC 7515) —— payload lisible, résistance à la manipulation. JWE (RFC 7516) chiffre le payload pour la confidentialité. Les JWT courants que vous voyez au quotidien sont des JWS.
À quoi sert le claim kid ?
kid est un champ d’en-tête (pas un claim du payload) qui identifie quelle clé du JWKS a signé le token, pour que le vérificateur choisisse la bonne. Cherchez-le contre un set de clés fixe que vous contrôlez —— ne lui faites pas confiance comme chemin ou URL.
Pourquoi alg: "none" est-il dangereux ?
Ça signifie « pas de signature ». Un vérificateur permissif qui respecte l’algorithme déclaré par le token lui-même acceptera n’importe quel payload forgé. Configurez toujours votre bibliothèque avec l’algorithme exact attendu (par ex. ['RS256']) et rejetez explicitement none.
Inspectez les tokens localement
- Encodeur et décodeur Base64 —— décodez les sections header/payload d’un JWT dans votre navigateur
- Base64 n’est pas du chiffrement —— pourquoi n’importe qui peut lire un payload JWT
- Pourquoi ne pas coller du JSON sensible en ligne —— manipuler de vrais tokens en toute sécurité
- RFC 7519 : JSON Web Token —— le standard lui-même