Tous les articles

JWT : structure du token et ce que signifie « décoder » un JWT

JWT (JSON Web Token) est un format compact pour transmettre des données signées, le plus souvent des informations sur un utilisateur authentifié. Un token comporte trois parties séparées par des points : header.payload.signature. En France, son usage est indissociable des obligations du RGPD dès qu'on y place la moindre donnée personnelle.

Les accents dans les claims, et le RGPD en toile de fond

Un payload comme {"nom": "François Léger", "ville": "Orléans"} s'encode en Base64URL exactement comme n'importe quel autre JSON — l'opération travaille sur des octets UTF-8, peu importe la langue. Le vrai sujet côté français n'est pas technique mais réglementaire : la CNIL considère un JWT contenant des données personnelles (nom, e-mail, rôle) comme un traitement de données à encadrer, avec une durée de vie du token qui doit rester proportionnée à sa finalité — un détail que beaucoup d'équipes découvrent seulement lors d'un audit RGPD.

Les trois parties d'un token

  • Header — un JSON contenant le type de token et l'algorithme de signature (par exemple HS256 ou RS256), encodé en Base64URL.
  • Payload — un JSON avec les « claims » : données utilisateur, date d'émission, expiration, etc., également en Base64URL.
  • Signature — une signature calculée sur le header et le payload avec une clé secrète ou privée, confirmant que le token n'a pas été altéré.

Base64URL, pas du Base64 classique

JWT utilise une variante de Base64 à alphabet sûr pour les URL : les caractères + et / sont remplacés par - et _, et le remplissage = est généralement omis. Cela permet d'insérer un token dans une URL ou un en-tête sans encodage supplémentaire.

Une distinction importante : décoder ≠ vérifier

Le header et le payload ne sont que du Base64URL : n'importe qui peut les décoder et lire leur contenu sans aucune clé. Décoder un token ne prouve pas que les données n'ont pas été modifiées. On ne peut faire confiance au contenu d'un token qu'après avoir vérifié sa signature avec la clé correspondante — et cette vérification est faite côté serveur, pas par un client qui se contente de regarder ce qu'il y a dans le token.

Attaque dangereuse : substitution de l'algorithme par « none »

La spécification JWT autorise l'algorithme none — un token sans signature. Si le backend fait naïvement confiance au champ alg de l'en-tête du token au lieu de vérifier la signature avec un algorithme fixe et connu à l'avance, un attaquant peut remplacer alg par none, retirer la signature, et le token passera la vérification avec des données arbitraires. Les bibliothèques JWT robustes exigent de préciser explicitement l'algorithme attendu lors de la vérification, précisément pour se prémunir de cette attaque.

Symfony et l'écosystème LexikJWTAuthenticationBundle

Dans l'écosystème PHP francophone, le bundle LexikJWTAuthenticationBundle pour Symfony reste l'un des moyens les plus répandus d'ajouter une authentification par JWT à une API — il génère par défaut des tokens signés en RS256 avec une paire de clés, ce qui rend le décodage du payload (lisible sans clé) et la vérification de la signature (qui nécessite la clé publique) une distinction très concrète à comprendre dès la mise en place du bundle.

Essayer l'outil