Contenu d'un JWT : décoder n'est pas vérifier
Un JSON Web Token (JWT) est constitué de trois morceaux de texte reliés par des points : un en-tête, une charge utile et une signature. Les deux premiers ne sont qu'encodés, pas chiffrés, donc quiconque détient le jeton peut les lire. La signature permet à un serveur de vérifier qu'une partie de confiance a bien émis le jeton et que personne ne l'a modifié. Décoder un jeton indique ce qu'il dit. Seule sa vérification indique s'il faut lui faire confiance.
Décodeur JWTJeton expiré, ou encore valide ?Essayer gratuitementLes trois parties
Un jeton ressemble à header.payload.signature. La première partie du jeton d'exemple bien connu de jwt.io est :
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
Chacune des deux premières parties est du JSON converti en base64url, une forme de texte sans risque dans une URL. La première partie se décode en :
{"alg":"HS256","typ":"JWT"}
La charge utile du même exemple se décode en :
{"sub":"1234567890","name":"John Doe","iat":1516239022}
La charge utile contient les revendications (claims), c'est-à-dire des affirmations sur l'utilisateur ou la session. La signature est calculée à partir des deux premières parties et d'une clé : modifier un seul caractère la rend invalide. Le base64url ne nécessite aucune clé pour être inversé, donc ne placez jamais un mot de passe, une clé privée ou des données personnelles dans une charge utile.
Revendications enregistrées
La RFC 7519, la norme des JWT, réserve quelques noms de revendications courts :
iss(émetteur) : qui a créé le jeton.sub(sujet) : la personne concernée par le jeton, généralement un identifiant d'utilisateur.aud(audience) : le service auquel le jeton est destiné.exp(date d'expiration) : l'instant à partir duquel le jeton n'est plus valide.nbf(pas avant) : l'instant le plus tôt à partir duquel le jeton est valide.iat(émis le) : le moment de création du jeton.
Les dates sont exprimées en secondes depuis le 1er janvier 1970 UTC, appelées temps Unix. L'exemple n'a pas de exp : selon la norme, il n'expire donc jamais. Un vrai jeton devrait en avoir un. Les autres noms, comme role ou email, relèvent de l'application.
Décoder n'est pas vérifier
Décoder consiste à découper le jeton aux points, à inverser le base64url et à lire le JSON. Cela montre ce que le jeton affirme, et cela fonctionne de la même façon pour un jeton falsifié, car n'importe qui peut écrire n'importe quelles revendications avec n'importe quelle signature.
Vérifier recalcule la signature avec la bonne clé et contrôle qu'elle correspond. Il vérifie aussi que exp et nbf encadrent l'heure actuelle, et que iss et aud ont les valeurs attendues par le service. Une application qui lit une revendication role sans vérifier fait confiance à celui qui a écrit le jeton. C'est une erreur courante.
HS256, RS256 et ES256
La valeur alg désigne la méthode. Trois sont courantes :
- HS256 est un HMAC avec SHA-256. Un seul secret partagé sert à signer et à vérifier, si bien qu'il doit rester sur le serveur qui émet les jetons.
- RS256 est une signature RSA avec SHA-256. L'émetteur signe avec une clé privée, et quiconque possède la clé publique peut vérifier. D'autres services peuvent contrôler les jetons sans pouvoir en créer.
- ES256 est une signature ECDSA sur la courbe P-256 avec SHA-256. Elle fonctionne comme RS256, avec des clés et des signatures plus petites.
Utilisez HS256 lorsqu'un seul service émet et contrôle ses jetons. Utilisez RS256 ou ES256 lorsque d'autres services doivent vérifier des jetons qu'ils n'ont pas émis.
Les problèmes liés à la confiance accordée à l'en-tête
L'en-tête est rédigé par celui qui envoie le jeton : le vérificateur ne doit donc pas le laisser choisir les règles.
alg: none. Un jeton sans signature peut déclarer"alg":"none". Certaines bibliothèques ont jadis accepté de tels jetons et ont sauté la vérification. Définissez les algorithmes autorisés dans votre propre code, ne les reprenez jamais du jeton.- Confusion d'algorithme. Un serveur attend du RS256 et détient une clé publique. Un attaquant envoie un jeton HS256 signé avec cette clé publique utilisée comme secret HMAC. Un vérificateur qui accepte l'algorithme indiqué par l'en-tête l'accepte. Liez chaque clé à un seul algorithme.
- Secrets faibles. L'attaquant dispose de l'en-tête, de la charge utile et de la signature : il peut tester des secrets candidats hors ligne. Un secret court ou un mot courant tombe rapidement face à une telle liste. La RFC 7518 indique qu'une clé HS256 doit faire au moins 256 bits et être aléatoire.
Coller un jeton de production dans un site
Un jeton valide et non expiré fonctionne pour quiconque le détient, jusqu'à son expiration. Traitez-le comme un mot de passe. Avant de coller un jeton dans un site, vérifiez si le site l'envoie à un serveur. Un outil qui s'exécute entièrement dans l'onglet du navigateur n'en a pas besoin. Vous pouvez contrôler n'importe quelle page en observant ses requêtes réseau dans les outils de développement du navigateur.
En général, les jetons ne peuvent pas être révoqués avant leur expiration, sauf si le serveur tient une liste. Si un jeton actif fuite, demandez au service de révoquer la session ou de renouveler ses clés. Utilisez un jeton de l'environnement de test pour le débogage chaque fois que possible. Le décodeur JWT lit les trois parties dans l'onglet de votre navigateur, et rien de ce que vous collez n'est envoyé ailleurs.
Webhooks : le même principe avec un secret partagé
La plupart des fournisseurs de webhooks envoient, dans un en-tête, un HMAC du corps de la requête, calculé avec un secret que vous partagez avec eux. Votre récepteur calcule le même HMAC et compare les deux valeurs. Les échecs courants sont minimes. Le JSON est reformaté avant le hachage, si bien que les octets changent. Le secret de test est utilisé sur du trafic réel. Ou les signatures sont comparées par une égalité de chaînes ordinaire, ce qui peut révéler des informations de temps de traitement. Utilisez une comparaison à temps constant.
Le testeur de signature webhook calcule la signature à partir du secret et du corps que vous collez, pour GitHub, Stripe, Slack, Shopify ou tout schéma HMAC, afin de voir si les deux valeurs correspondent.
Réponses rapides
Un JWT est-il chiffré ?
Non. Un JWT standard est signé, et n'importe qui peut lire son en-tête et sa charge utile. Seule la signature le protège contre les modifications.
Que se passe-t-il si je modifie la charge utile ?
La signature ne correspond plus, donc un serveur qui vérifie rejette le jeton. Lire les revendications ne contrôle pas la signature : le décodeur affiche donc quand même votre version modifiée.
Traduit de Version originale anglaise avec l’aide de l’IA.
Commentaires
Aucun commentaire pour l’instant. Soyez le premier.


