Décoder un JSON Web Token (JWT)

décode votre jeton JWT (JSON Web Token) et affiche les informations qu'il contient de manière lisible et structurée

Qu'est-ce qu'un JWT (JSON Web Token) ?

Un JSON Web Token, abrégé en JWT (prononcé "jot"), est un format compact défini par la RFC 7519 permettant de transporter une série de revendications (claims) entre deux parties. Le JWT, ou jeton JWT, est aujourd'hui le format dominant pour véhiculer une identité authentifiée dans une API HTTP. Un JWT se présente comme une chaîne ASCII composée de trois segments séparés par des points :

header.payload.signature

Chaque segment est encodé en Base64URL, une variante du Base64 sans padding = et qui remplace + par - et / par _ afin de pouvoir circuler dans une URL ou un en-tête HTTP sans échappement supplémentaire.

Important : un JWT n'est PAS chiffré. Le format JWT standard (JWS) est simplement signé : la signature garantit l'intégrité du contenu, mais n'apporte aucune confidentialité. N'importe qui peut décoder le payload d'un JWT avec un simple Base64URL inverse, comme le fait cet outil jwt decode en ligne.

Anatomie d'un JWT

Un json web token est composé de trois parties bien distinctes, chacune jouant un rôle précis dans le mécanisme d'authentification :

1. Header

Le header est un objet JSON qui décrit comment le token est signé. Il contient au minimum :

  • alg (algorithm) : l'algorithme de signature utilisé. Valeurs typiques : HS256, RS256, ES256, EdDSA.
  • typ (type) : le type du token, presque toujours "JWT".
  • kid (key ID) : facultatif, identifie quelle clé doit être utilisée pour vérifier la signature. Pratique en présence d'un parc de clés en rotation (JWKS).

2. Payload

Le payload contient les claims, c'est-à-dire les revendications que l'émetteur fait au sujet de l'utilisateur ou de la session. La RFC 7519 définit sept claims standards (registered claims) :

  • iss (issuer) : qui a émis le token, par exemple "https://accounts.google.com".
  • sub (subject) : à qui appartient le token, en pratique l'identifiant utilisateur.
  • aud (audience) : à qui le token est destiné. Évite qu'un token émis pour l'API A ne soit accepté par l'API B.
  • exp (expiration time) : timestamp Unix après lequel le token n'est plus valide.
  • nbf (not before) : timestamp avant lequel le token n'est pas encore actif.
  • iat (issued at) : timestamp d'émission du token.
  • jti (JWT ID) : identifiant unique du token, utilisé pour la révocation et la prévention du rejeu.

À ces claims standards s'ajoutent généralement des claims custom propres à l'application (roles, scope, tenant_id, email, permissions...).

3. Signature

La signature est un condensat cryptographique calculé sur base64url(header) + "." + base64url(payload) à l'aide d'une clé. C'est elle qui prouve que personne n'a modifié le header ni le payload depuis l'émission. Les algorithmes les plus courants :

  • HS256 / HS384 / HS512 : signature symétrique HMAC-SHA. Une clé secrète partagée entre l'émetteur et le vérificateur. Simple, mais inadapté dès qu'il y a plus d'un consommateur.
  • RS256 / RS384 / RS512 : signature asymétrique RSA. L'émetteur signe avec sa clé privée, n'importe quel consommateur vérifie avec la clé publique correspondante. Standard de fait pour OAuth2 et OpenID Connect.
  • ES256 / ES384 / ES512 : signature asymétrique ECDSA. Mêmes propriétés que RS256 mais avec des clés et signatures bien plus courtes.
  • EdDSA (Ed25519) : signature asymétrique moderne, rapide et compacte.

Encore une fois : la signature protège l'intégrité, pas la confidentialité. Le payload reste lisible par quiconque possède le token.

Pourquoi décoder un JWT ?

L'opération jwt token decode répond à plusieurs besoins concrets pour un développeur ou un ingénieur sécurité :

  • Debug d'authentification : votre API renvoie un 401 ou un 403, vous voulez voir ce qui se trouve réellement dans le payload (sub, scope, roles, exp) plutôt que de deviner.
  • Vérifier les claims : confirmer qu'un token contient bien la revendication attendue (par exemple tenant_id ou permissions) avant de chercher ailleurs dans la chaîne d'autorisation.
  • Lire l'expiration : convertir le timestamp exp en date humaine pour confirmer qu'un token est bien expiré, ou au contraire qu'il devrait encore être valide.
  • Audit de sécurité : s'assurer qu'un service tiers ne fuit pas d'informations sensibles dans le payload (e-mails, identifiants internes, données personnelles).
  • Formation et compréhension : voir concrètement à quoi ressemble un jsonwebtoken sortant d'un fournisseur OAuth (Google, Auth0, Keycloak, AWS Cognito) pour comprendre la mécanique sans plonger dans la doc.
  • Exploration de tokens publics : inspecter un JWT trouvé dans des logs, dans un cookie ou dans un échange OAuth interceptable.

Decoder vs Verifier : la distinction critique

Les deux opérations semblent voisines mais elles n'ont rien à voir en termes de garanties de sécurité :

  • Décoder un JWT consiste à découper la chaîne sur les . et à appliquer un Base64URL inverse aux deux premiers segments. C'est une simple lecture, à la portée de n'importe quel script de trois lignes. Aucune vérification de signature n'est faite.
  • Vérifier un JWT consiste à recalculer la signature à partir du header, du payload et d'une clé, puis à comparer le résultat à la signature présente dans le token. C'est ce qui garantit que le token n'a pas été falsifié.

Conclusion pratique : décoder ne vaut pas faire confiance. Tant que la signature n'a pas été vérifiée avec la bonne clé, le contenu du payload peut être totalement bidon. Pour la phase de confiance, utilisez notre JWT Verifier.

Comment l'utiliser

  1. Récupérez le JWT à inspecter, par exemple depuis un en-tête Authorization: Bearer <jwt>, depuis un cookie de session, depuis le localStorage du navigateur, ou depuis un log applicatif.
  2. Collez la chaîne complète dans le champ de saisie. Les trois segments doivent rester séparés par des points.
  3. L'outil affiche immédiatement le header décodé en JSON formaté, avec l'algorithme et le type.
  4. Le payload est ensuite décodé et affiché. Vous y voyez tous les claims standards et custom.
  5. L'outil indique aussi l'information de signature (algorithme déclaré, longueur), sans la vérifier.
  6. Pour confirmer que le token n'a pas été falsifié, basculez vers notre JWT Verifier avec la clé publique ou le secret attendu.

Tout le décodage est effectué dans votre navigateur en JavaScript : votre token n'est jamais envoyé à nos serveurs.

JWT et sécurité : les pièges à éviter

Ne stockez JAMAIS de données sensibles dans le payload d'un JWT signé.

Mots de passe, numéros de carte bancaire, données médicales, secrets d'API, identifiants internes critiques : tout ce qui se trouve dans le payload est lisible par quiconque possède le token, y compris l'utilisateur lui-même via les outils de développement de son navigateur. La signature ne masque rien, elle ne fait que prouver que l'émetteur est bien celui qu'il prétend être.

Quelques règles d'or pour bien utiliser les JWT en production :

  • Toujours vérifier la signature côté serveur avant d'accorder le moindre droit. Notre JWT Verifier illustre exactement cette opération.
  • Préférer RS256 ou ES256 à HS256 pour les API publiques. La signature asymétrique évite de partager un secret entre l'émetteur et chaque consommateur.
  • Toujours respecter le claim exp. Un JWT sans expiration ou avec une expiration trop lointaine est une bombe à retardement en cas de fuite.
  • Valider iss et aud côté serveur, pour éviter qu'un token légitime émis pour un autre service soit accepté par erreur.
  • Refuser alg: "none" côté vérification. C'est une faille classique qui permet à un attaquant de forger n'importe quel payload.
  • Garder les durées de vie courtes (15 minutes par exemple) et coupler avec un refresh token plus long mais révocable côté serveur.

Exemple de jeton JWT décodé

Voici un JWT typique :

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjMiLCJuYW1lIjoiSm9obiIsImlhdCI6MTUxNjIzOTAyMn0.jrU9j8LZcRK2_BZjqXjU7lEpJbkqmXfTQIu9vT45j-I

Une fois décodé, voici son contenu :

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

// Payload
{
  "sub": "123",
  "name": "John",
  "iat": 1516239022
}

// Signature (binaire, encodé en Base64URL)
HMACSHA256(
  base64url(header) + "." + base64url(payload),
  secret
)

Où trouver un JWT à copier ?

En pratique, un JWT à déchiffrer (au sens de décoder) provient le plus souvent d'un de ces emplacements :

  • Cookie HTTP : ouvrez les outils de développement (F12), onglet Application ou Storage, puis Cookies. Repérez un cookie nommé access_token, jwt, session ou similaire.
  • localStorage / sessionStorage : même panneau, section Local Storage. Beaucoup de SPA y stockent leur token sous une clé token ou auth.
  • En-tête Authorization : onglet Network, sélectionner une requête API, lire l'en-tête Authorization: Bearer <jwt>. Copier uniquement la partie après Bearer .
  • Logs serveur : un JWT apparaît parfois dans les logs d'une passerelle ou d'un reverse proxy (à éviter en production, mais utile en debug).

Questions fréquentes

Le JWT est-il chiffré ou en clair ?

Un JWT signé (format JWS) est seulement encodé en Base64URL, pas chiffré. Toute personne qui intercepte un token peut lire le payload en quelques secondes. Si vous devez transporter des données vraiment confidentielles dans le token, il faut utiliser le format JWE (JSON Web Encryption), qui ajoute une couche de chiffrement par-dessus la signature. En pratique, le JWE reste rare : on préfère ne pas mettre de données sensibles dans un jeton et conserver les informations critiques en base côté serveur.

Comment révoquer un JWT avant son expiration ?

C'est l'un des points faibles du JWT : par construction, le serveur n'a pas besoin de stocker l'état du token, donc il ne sait pas non plus comment le marquer comme révoqué. Trois approches existent. Liste de révocation : maintenir côté serveur la liste des jti invalidés, et la consulter à chaque requête. Durées de vie courtes : émettre des access tokens valides 5 à 15 minutes, et utiliser un refresh token révocable côté serveur pour en générer de nouveaux. Rotation de clé de signature : invalider toute une génération de tokens en changeant la clé. La deuxième approche est de loin la plus répandue.

Quelle différence entre un JWT et une session classique ?

Une session classique stocke un identifiant opaque côté client (généralement dans un cookie) et conserve toutes les données associées (utilisateur, droits, expiration) en mémoire ou en base côté serveur. Un JWT, au contraire, transporte directement ces données dans le token signé. Avantage du JWT : le serveur n'a pas besoin de stocker de session, ce qui simplifie le scaling horizontal et l'architecture microservices. Inconvénients : la révocation est plus complexe, le token est plus volumineux à chaque requête, et la moindre fuite expose le payload.

Différence entre JWT, JWS et JWE ?

JWT (RFC 7519) est un format de jeton générique. Il peut être implémenté de deux manières concrètes : JWS (RFC 7515, JSON Web Signature) qui se contente de signer le payload, et JWE (RFC 7516, JSON Web Encryption) qui le chiffre. En pratique, quand on parle de "JWT" sans précision, on parle presque toujours d'un JWS : un token signé mais lisible par tous. Le JWE est utilisé dans les contextes où la confidentialité du payload est indispensable, par exemple dans certains scénarios OpenID Connect avancés.

Mon JWT n'est pas accepté par l'API, pourquoi ?

Les causes classiques sont, par ordre de fréquence : token expiré (vérifiez le claim exp), signature invalide (clé secrète ou clé publique ne correspond pas à celle utilisée par l'émetteur), mauvais aud (le token a été émis pour un autre service), mauvais iss (l'émetteur déclaré n'est pas celui attendu), algorithme refusé (l'API exige par exemple RS256 et reçoit un HS256), horloges désynchronisées entre l'émetteur et le vérificateur (joue sur exp et nbf). Décoder le token avec cet outil permet déjà d'éliminer la moitié des hypothèses en lisant directement les claims.

Comment générer un JWT ?

La plupart des langages disposent d'une bibliothèque dédiée : jsonwebtoken en Node.js, PyJWT en Python, lcobucci/jwt ou firebase/php-jwt en PHP, jjwt en Java, golang-jwt/jwt en Go. Toutes prennent en entrée un objet payload, une clé et un algorithme, et retournent la chaîne header.payload.signature prête à être envoyée. Il est fortement déconseillé d'implémenter la génération à la main : la cryptographie comporte trop de pièges (comparaisons non constantes, gestion incorrecte de alg: none, etc.).

Le decoder accepte-t-il un JWT expiré ?

Oui. Le decoder se contente d'afficher le contenu du token sans porter de jugement sur sa validité temporelle. Il n'évalue ni exp, ni nbf, ni la signature. C'est utile pour comprendre pourquoi un token a été rejeté par une API : on peut comparer la valeur de exp à l'heure actuelle pour confirmer qu'il est bien expiré.

Mon JWT est-il valide si le decoder l'affiche correctement ?

Non. L'affichage prouve uniquement que la chaîne est bien formée (trois segments séparés par des points, encodage Base64URL correct, JSON valide dans le header et le payload). Cela ne dit rien de l'authenticité du token. Un JWT entièrement falsifié peut s'afficher sans erreur dans un decoder, c'est précisément pour cela qu'on doit le passer à un verifier.

Exemple de requête

curl -X POST https://cdrn.fr/api/v1/tools/jwt-decoder/execute \
  -H "Content-Type: application/json" \
  -d '{"token":"..."}'

Schéma d'entrée

Champ Type Requis Défaut
token text

Points d'accès

  • GET https://cdrn.fr/api/v1/tools - liste tous les outils disponibles
  • GET https://cdrn.fr/api/v1/tools/jwt-decoder - récupère le schéma de cet outil
  • POST https://cdrn.fr/api/v1/tools/jwt-decoder/execute - exécute cet outil avec un payload JSON