Pourquoi j'ai créé ce décodeur JWT
Après des années à implémenter des systèmes d'authentification basés sur JWT dans diverses applications (APIs REST, microservices, Single Page Applications), j'ai réalisé à quel point un bon outil de décodage est essentiel pour le débogage quotidien. Quand un utilisateur signale "je ne peux plus accéder à mon compte", la première chose que je fais est d'inspecter son token : est-il expiré ? Le claim "role" est-il correct ? L'audience correspond-elle ?
Ce décodeur vous permet d'analyser instantanément n'importe quel JWT, de visualiser son header et payload de manière structurée, et de vérifier les claims temporels (exp, iat, nbf) avec leur conversion en date lisible. Tout se passe dans votre navigateur — aucune donnée n'est envoyée à un serveur.
Qu'est-ce qu'un JWT et pourquoi est-il si populaire ?
Un JSON Web Token (JWT, prononcé "jot") est un standard ouvert (RFC 7519) permettant de transmettre des informations de manière sécurisée entre deux parties sous forme d'objet JSON signé. Contrairement aux sessions traditionnelles qui nécessitent un stockage côté serveur, les JWT sont "stateless" — toutes les informations nécessaires sont contenues dans le token lui-même.
Cette propriété stateless rend les JWT particulièrement adaptés aux architectures modernes : microservices, APIs RESTful, authentification cross-domain, et Single Sign-On (SSO). Un serveur n'a besoin que de la clé de vérification pour valider un token — pas d'accès à une base de données de sessions.
Anatomie détaillée d'un JWT
Un JWT se compose de trois parties séparées par des points (.), chacune encodée en Base64URL :
xxxxx.yyyyy.zzzzz → header.payload.signature
📝 Header (En-tête JOSE)
Le header contient les métadonnées du token : le type ("typ": "JWT") et l'algorithme de signature ("alg": "HS256", "RS256", "ES256", etc.). C'est une information critique — elle indique au récepteur comment vérifier la signature. Certains headers incluent aussi "kid" (key ID) pour identifier quelle clé utiliser dans un système avec rotation de clés.
Exemple : {"alg": "RS256", "typ": "JWT", "kid": "abc123"}
📦 Payload (Charges utiles / Claims)
Le payload contient les "claims" — les affirmations que le token fait sur l'utilisateur ou le contexte. Il existe des claims réservés (iss, sub, exp...), des claims publics (définis dans le registre IANA), et des claims privés (spécifiques à votre application comme "role", "permissions", "user_id").
ATTENTION : Le payload est encodé en Base64, pas chiffré ! N'importe qui peut le décoder. Ne mettez JAMAIS de mots de passe, clés API, ou données sensibles dans un JWT.
🔐 Signature (Vérification d'intégrité)
La signature est calculée en prenant le header encodé, le payload encodé, et une clé secrète (ou privée), puis en appliquant l'algorithme spécifié dans le header. Elle garantit que le token n'a pas été altéré — si un seul bit du header ou payload change, la signature ne correspondra plus.
Formule : HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
Les claims réservés (Registered Claims) en détail
Ces claims sont définis dans la RFC 7519 et ont une sémantique précise. Leur utilisation n'est pas obligatoire mais fortement recommandée :
- iss (Issuer) : Identifie l'émetteur du token. Généralement l'URL de votre serveur d'authentification (ex: "https://auth.example.com"). Permet de rejeter les tokens émis par des sources non autorisées.
- sub (Subject) : Le sujet du token, généralement l'identifiant unique de l'utilisateur (UUID, email, etc.). Doit être unique dans le contexte de l'issuer.
- aud (Audience) : Les destinataires prévus du token. Peut être une chaîne ou un tableau. Un service ne doit accepter que les tokens où son identifiant apparaît dans l'audience.
- exp (Expiration Time) : Timestamp Unix après lequel le token est invalide. Vérification critique côté serveur — un token expiré doit être systématiquement rejeté.
- nbf (Not Before) : Timestamp Unix avant lequel le token n'est pas valide. Utile pour les tokens programmés à l'avance.
- iat (Issued At) : Timestamp de création du token. Permet de calculer l'âge du token et potentiellement de rejeter les tokens trop anciens.
- jti (JWT ID) : Identifiant unique du token (généralement un UUID). Permet d'éviter les attaques par rejeu en maintenant une liste des jti utilisés.
Algorithmes de signature : HS256 vs RS256 vs ES256
🔑 HS256 (HMAC + SHA-256) — Symétrique
Utilise une clé secrète unique pour signer ET vérifier. Simple à implémenter, performant. Inconvénient majeur : la clé secrète doit être partagée avec tous les services qui doivent vérifier les tokens. Risque de compromission si un service est piraté.
Cas d'usage : Applications monolithiques, environnements où tous les services sont de confiance.
🔐 RS256 (RSA + SHA-256) — Asymétrique
Utilise une paire clé privée (pour signer) / clé publique (pour vérifier). Seul le serveur d'authentification détient la clé privée. Les services n'ont besoin que de la clé publique, qui peut être distribuée librement (souvent via JWKS endpoint).
Cas d'usage : Microservices, SSO, APIs publiques, OAuth2/OIDC.
🛡️ ES256 (ECDSA + SHA-256) — Courbes elliptiques
Asymétrique comme RS256, mais basé sur les courbes elliptiques. Signatures plus courtes et calcul plus rapide que RSA pour un niveau de sécurité équivalent. De plus en plus recommandé pour les nouvelles implémentations.
Cas d'usage : Applications mobiles, IoT, environnements avec contraintes de bande passante.
Sécurité JWT : les pièges à éviter absolument
- Vulnérabilité "alg: none" : Certaines bibliothèques mal configurées acceptent des tokens sans signature si le header indique "alg": "none". TOUJOURS vérifier l'algorithme côté serveur et rejeter "none".
- Confusion d'algorithme : Un attaquant peut changer "RS256" en "HS256" et utiliser la clé publique (connue) comme clé secrète HMAC. Vérifiez toujours que l'algorithme correspond à celui attendu.
- Clés faibles : Pour HS256, utilisez une clé d'au moins 256 bits (32 caractères) générée aléatoirement. Une clé faible peut être brute-forcée.
- Stockage non sécurisé : localStorage est accessible par n'importe quel script JS sur la page (vulnérable au XSS). Préférez les cookies httpOnly + Secure + SameSite.
- Absence de vérification d'expiration : Vérifiez TOUJOURS exp côté serveur. Ne faites jamais confiance au client pour cette vérification.
- Données sensibles dans le payload : Le payload est LISIBLE par tous. Jamais de mots de passe, secrets, ou données personnelles sensibles.
Bonnes pratiques d'implémentation
- Durées d'expiration courtes : 15 minutes à 1 heure pour les access tokens. Utilisez des refresh tokens (7-30 jours) stockés de manière sécurisée pour renouveler sans ré-authentification.
- Rotation des clés : Prévoyez un mécanisme de rotation de clés (JWKS avec kid) pour pouvoir changer de clé sans invalider tous les tokens existants.
- Validez tous les claims pertinents : iss, aud, exp au minimum. Ne faites jamais confiance aveuglément au contenu du token.
- Utilisez des bibliothèques éprouvées : jsonwebtoken (Node.js), PyJWT (Python), java-jwt (Java), etc. N'implémentez pas votre propre vérification de signature.
- Loggez les échecs d'authentification : Tokens expirés, signatures invalides, audiences incorrectes... Ces logs sont précieux pour détecter les attaques.
Traitement 100% local : votre sécurité est préservée
Ce décodeur fonctionne entièrement dans votre navigateur. Le token que vous collez n'est jamais envoyé à nos serveurs — le décodage Base64 et l'analyse JSON s'effectuent en JavaScript côté client. Vous pouvez le vérifier dans l'onglet Réseau de vos DevTools : aucune requête réseau n'est émise lors du décodage.
Cela dit, pour des tokens de production contenant des informations sensibles (même si elles ne devraient pas y être), préférez des outils complètement hors ligne comme la commande jwt-cli ou des scripts locaux.