Un JWT signé a la forme header.payload.signature, chaque partie étant encodée en base64url sans remplissage : l’en-tête désigne l’algorithme (alg), la clé (kid) et le type (typ), et la charge utile contient des claims comme iss, sub, aud, exp, nbf, iat et jti (RFC 7519 §4.1), ainsi que les claims propres à l’application. Les JWT chiffrés comportent cinq parties. La charge utile d’un JWT signé est lisible par quiconque détient le jeton : la signature protège l’intégrité, pas la confidentialité.
La vérification comporte deux volets : la signature, avec un algorithme et une clé que le vérificateur a choisis à l’avance, puis les claims – émetteur, audience, expiration avec une petite tolérance de décalage d’horloge, et type de jeton, pour qu’un jeton d’ID ne soit pas accepté là où un jeton d’accès est attendu. La RFC 8725 (JWT Best Current Practices) énumère ces règles ; la plupart des vulnérabilités des JWT proviennent de l’omission de l’une d’elles.
Le choix de l’algorithme est un compromis, traité dans ES256 vs RS256 et HS256 vs RS256. Le débogueur JWT décode et vérifie les jetons localement.