Comment fonctionne JWT et comment décoder un jeton en toute sécurité
Comprendre la structure des jetons Web JSON, comment les signatures sont créées et vérifiées, les revendications courantes, les pièges de sécurité et comment décoder un JWT.
· 6 min de lecture
Les jetons Web JSON (JWT) sont partout: connexions OAuth et OpenID Connect, passerelles API, connexion unique entre microservices et sessions d'applications mobiles. Ils sont aussi largement mal compris. Les développeurs décodent un jeton, voient un JSON lisible et se demandent si c'est un problème de sécurité; d'autres stockent des données sensibles dans des jetons, en supposant qu'ils sont cryptés. Cet article explique exactement ce qu'est un JWT, comment il est validé et comment l'inspecter sans créer de risque.
Les trois parties d'un JWT
Une JWT ressemble à trois chaînes aléatoires reliées par des points:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI0MiIsImV4cCI6MTkwMDAwMDAwMH0.Kx8...
Chaque partie est codée par Base64URL:
- Header JSON décrivant le type de jeton et l'algorithme de signature, par exemple
{"alg":"HS256","typ":"JWT"}. - ** Payload** JSON contenant des revendications: déclarations sur l'utilisateur et le jeton, telles que
{"sub":"42","exp":1900000000}. - Signature octets calculés à partir de l'en-tête et de la charge utile avec une clé secrète ou privée.
Base64URL est une variante de [Base64] ((/blog/base64-expliqué) qui utilise - et _ au lieu de + et / et laisse tomber le rembourrage, de sorte que les jetons peuvent être placés dans les URL et les en-têtes sans s'échapper.
Crucialement, l'en-tête et la charge sont seulement codés, pas chiffrés. Tous ceux qui ont le jeton peuvent les lire. Collez un jeton dans un [JWT décodeur] ((/tools/jwt-decodeur) et la charge utile apparaît instantanément c'est par conception.
Comment fonctionne la signature
La signature est ce qui rend un JWT digne de confiance. L'émetteur prend l'en-tête codé et la charge utile, les relie avec un point, et signe cette chaîne.
Avec HS256 (HMAC avec SHA-256), l'émetteur et le vérificateur partagent une clé secrète:
signature = HMAC-SHA256(secret, base64url(header) + "." + base64url(payload))
Avec RS256 ou ES256, l'émetteur signe avec une clé privée et n'importe qui peut vérifier avec la clé publique correspondante, souvent publiée à un point final JWKS tel que https://login.example.com/.well-known/jwks.json. Les algorithmes asymétriques sont préférés lorsque de nombreux services doivent vérifier les jetons, mais qu'un seul devrait les émettre.
Quand un serveur reçoit un jeton, il recompte ou vérifie la signature. Si même un seul caractère de la charge utile change disons qu'un attaquant a modifié "role":"user" en "role":"admin" la signature ne correspond plus et le jeton est rejeté.
Les réclamations enregistrées que vous devriez connaître
La spécification JWT (RFC 7519) définit les noms de revendications standard:
iss(émetteur): qui a créé le jeton, par exemplehttps://login.example.com.sub(sujet): à qui le jeton concerne, généralement un identifiant utilisateur.aud(audience): à qui le jeton est destiné, tel queapi.example.com.exp(expiration): le temps après lequel le jeton doit être rejeté, en [secondes Unix] ((/blog/unix-timestamp-explained).nbf(pas avant): l'heure avant laquelle le jeton n'est pas valide.iat(émis à): lorsque le jeton a été créé.jti(JWT ID): un identifiant unique, utile pour les listes de révocation.
Les demandes ajoutent leurs propres revendications: scope, roles, tenant_id, email. Gardez-les peu nombreux; chaque revendication voyage avec chaque demande.
Valider correctement un jeton
Un serveur doit vérifier tout ce qui suit, dans cet ordre:
- L'algorithme est celui que vous attendez. Configurez une liste d'autorisation telle que
["RS256"]. Ne laissez jamais l'en-tête du jeton décider librement; les vulnérabilités historiques permettent aux attaquants de passer ànoneou de tromper les serveurs en utilisant une clé publique comme secret HMAC. - La signature est valide avec la bonne clé, choisie par
kidparmi votre ensemble de clés de confiance. expest dans le futur etnbfest dans le passé, ce qui permet un petit décalage horaire de 3060 secondes.isscorrespond exactement à votre fournisseur d'identité.audcontient l'identifiant de votre service, donc un jeton émis pour une autre API ne peut pas être reproduit contre le vôtre.
Utilisez une bibliothèque maintenue jose pour JavaScript, PyJWT pour Python, golang-jwt pour Go plutôt que d'écrire vous-même la vérification.
Décodage contre vérification
Décodage signifie Base64URL-décodage des deux premières parties et analyse du JSON. Il n'a pas besoin de clé et ne prouve rien sur l'authenticité. Il est utile pour:
- Déboguer pourquoi une API renvoie 401: est-ce que
audest correct ? Le jeton a expiré ? - Vérification des champs d'application ou des rôles accordés par un flux de connexion.
- Confirmant qu'un rafraîchissement de jeton a produit un nouveau
exp.
Vérifier signifie vérifier la signature et les revendications comme décrit ci-dessus. Seuls les serveurs devraient prendre des décisions d'autorisation, et seulement après vérification.
Le code front-end peut décoder un jeton pour afficher le nom de l'utilisateur ou planifier un rafraîchissement avant exp, mais il ne doit jamais s'appuyer sur des revendications décodées pour la sécurité, car un utilisateur peut modifier tout ce qui s'exécute dans son navigateur.
Où stocker les jetons dans le navigateur
Il n'y a pas de réponse parfaite, seulement des compromis:
- ** Les cookies HttpOnly, Secure, SameSite** ne peuvent pas être lus par JavaScript, qui protège contre le vol de jetons par le biais de scripts cross-site. Ils nécessitent une protection CSRF, bien que SameSite=Lax ou Strict couvre la plupart des cas.
- Memory (une variable JavaScript) est à l'abri de la persistance mais perdue lors du rechargement; combinez-le avec un jeton de rafraîchissement dans un cookie HttpOnly.
- localStorage est pratique mais lisible par n'importe quel script sur la page, donc une seule vulnérabilité XSS fuit chaque jeton.
Pour la plupart des applications Web, les jetons d'accès de courte durée dans la mémoire plus un jeton de rafraîchissement dans un cookie HttpOnly sont un bon équilibre.
Expiration et révocation
Les JWT sont sans état: un serveur peut les valider sans recherche de base de données. L'inverse est qu'un jeton valide ne peut pas être révoqué avant son expiration. Les mesures d'atténuation
- Garder les jetons d'accès de courte durée 5 à 15 minutes est courant.
- Utiliser des jetons de mise à jour, stockés en toute sécurité et vérifiés par rapport à une base de données, pour émettre de nouveaux jetons d'accès.
- Pour les actions à risque élevé, vérifiez une liste de révocation des valeurs
jtiou un horodatage "tokens valides après" par utilisateur.
Erreurs courantes
- Mettre des secrets dans la charge utile. Les mots de passe, les clés d'API et les données personnelles sont lisibles par toute personne possédant le jeton. Si vous avez besoin de confidentialité, utilisez JWE (tokens cryptés) ou gardez les données côté serveur.
- Un jeton volé valable un an est une violation d'un an.
- Suivi des vérifications d'audience. Sans validation
aud, un jeton pour un service à faible privilège peut être utilisé contre un service à haut privilège. - Secrets HMAC faibles. Les secrets HS256 doivent être longs et aléatoires au moins 256 bits. Des secrets courts peuvent être forcés hors ligne à partir d'un seul jeton.
- Logging tokens. Les journaux d'accès et les détecteurs d'erreurs capturent souvent les en-têtes
Authorization. Rédigez-les.
Inspecter un jeton en toute sécurité
Lors du débogage, utilisez un décodeur qui s'exécute localement dans votre navigateur afin que le jeton ne soit jamais envoyé à un tiers. Préférer les jetons expirés ou d'environnement de test lors du partage de captures d'écran ou du collage dans les tickets. Vérifiez:
algetkiddans l'en-tête correspondent à la configuration de votre fournisseur.issetaudcorrespondent à ce que votre API attend.exp,iatetnbfont du sens par rapport à l'heure actuelle.- Les objectifs et les rôles contiennent ce dont l'opération a besoin.
Résumé
Un JWT est un ensemble signé, non chiffré, de revendications JSON. Sa sécurité provient entièrement de la vérification de la signature et de la validation des réclamations sur le serveur. Le décryptage est inoffensif et utile pour le débogage; faire confiance aux données décodées sans vérification est le risque réel. Gardez les jetons de courte durée, gardez les charges utiles petites et exemptes de secrets, vérifiez l'algorithme, la signature, l'expiration, l'émetteur et l'audience à chaque fois, et inspectez les jetons avec des outils qui les gardent sur votre machine.
Cette page a été traduite automatiquement depuis l'anglais. Si vous repérez une erreur, dites-le-nous.