Vérifier la signature d'un JSON Web Token (JWT)

vérifie la signature d'un JWT (HS256, HS384, HS512, RS256, RS384, RS512) à partir d'un secret ou d'une clé publique, et inspecte ses claims
Pour HS256 / HS384 / HS512 : la chaîne secrète. Pour RS256 / RS384 / RS512 : la clé publique au format PEM.

Pourquoi vérifier la signature d'un JWT ?

Un JSON Web Token (JWT) se décompose en trois parties séparées par des points : header.payload.signature. Décoder un JWT consiste simplement à lire les deux premières parties (qui sont du Base64URL). N'importe qui peut le faire, et n'importe qui peut fabriquer un JWT avec le payload de son choix. Ce qui rend un JWT digne de confiance, c'est uniquement la signature : sans vérification, accepter un JWT revient à laisser entrer chez vous toute personne qui prétend être quelqu'un, sans demander de pièce d'identité.

Cet outil vérifie la signature d'un JWT à partir d'une clé. Il ne se contente pas de décoder : il recalcule la signature à partir du header, du payload et de votre clé, puis la compare avec la signature du token. Si les deux concordent, le token est authentique. Sinon, il a été forgé, modifié, ou signé avec une autre clé.

La vérification est la pierre angulaire de toute architecture qui utilise des JWT pour l'authentification ou l'autorisation : sans signature valide, le payload peut mentir. Un attaquant qui modifierait "role":"user" en "role":"admin" n'aurait aucune difficulté à le faire si le serveur ne vérifiait que le format du token et pas sa signature.

Algorithmes courants

La spécification JWT (RFC 7518, JSON Web Algorithms) définit plusieurs familles d'algorithmes. Voici les plus utilisées en production :

  • HMAC (HS256, HS384, HS512) : signature symétrique à base de HMAC-SHA. La même clé secrète sert à signer et à vérifier. Simple à mettre en place, performant, mais toute partie capable de vérifier le token est aussi capable d'en émettre. Adapté aux scénarios où l'émetteur et le vérificateur sont la même équipe ou le même service.
  • RSA (RS256, RS384, RS512) : signature asymétrique. La clé privée signe, la clé publique vérifie. Idéal lorsque l'émetteur et les vérificateurs sont des entités distinctes (OAuth2, OpenID Connect, fédération d'identité). C'est l'algorithme privilégié par la plupart des fournisseurs d'identité publics.
  • ECDSA (ES256, ES384) : signature asymétrique sur courbes elliptiques. Même logique que RSA (clé privée pour signer, clé publique pour vérifier) mais avec des clés et signatures plus compactes pour un niveau de sécurité équivalent. De plus en plus répandu dans les architectures modernes.

Comment fournir la clé

Le format de la clé attendue dépend de l'algorithme déclaré dans le header du JWT :

  • HS256, HS384, HS512 : la clé est une chaîne secrète (string). C'est le secret partagé avec l'émetteur, souvent stocké dans une variable d'environnement comme JWT_SECRET. Aucune mise en forme particulière, juste la valeur brute.
  • RS256, RS384, RS512 : la clé est une clé publique RSA au format PEM, qui commence par -----BEGIN PUBLIC KEY----- et se termine par -----END PUBLIC KEY-----. Conservez les retours à la ligne tels quels, sinon OpenSSL refuse de la parser.
  • ES256, ES384 : la clé est une clé publique ECDSA au format PEM, sur la courbe correspondante (P-256 pour ES256, P-384 pour ES384).

Exemple de clé publique RSA attendue

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxe...
...vQIDAQAB
-----END PUBLIC KEY-----

Comment fonctionne la vérification ?

Notre serveur reproduit exactement l'opération qu'a faite l'émetteur :

  1. Il sépare le JWT en header, payload et signature.
  2. Il concatène base64url(header) + "." + base64url(payload).
  3. Pour HMAC, il calcule un HMAC-SHA-256/384/512 avec votre clé secrète, puis compare avec la signature reçue via hash_equals (comparaison à temps constant pour éviter les attaques temporelles).
  4. Pour RSA, il appelle openssl_verify avec votre clé publique au format PEM.

Cas d'usage

  • Debug d'authentification API : vous recevez un 401, vérifiez si votre token est bien signé avec la clé attendue.
  • Validation d'un token reçu d'un fournisseur : un partenaire (Auth0, Keycloak, Cognito, Okta) vous envoie des JWT signés en RS256 ; vous voulez confirmer qu'ils proviennent bien de lui avec sa clé publique.
  • Audit de sécurité : vérifier qu'un service tiers signe correctement ses tokens avec un algorithme robuste, et pas en HS256 avec un secret faible.
  • Tests manuels : vérifier qu'un JWT généré par votre code passe bien la vérification avec la clé publique fournie.
  • Vérification rapide d'un token reçu : pendant l'intégration d'un SSO ou d'une API partenaire, vérifier en quelques secondes que la chaîne signature/clé fonctionne avant d'écrire la moindre ligne de code.

Comment utiliser l'outil

  1. Collez le JWT complet (les trois parties séparées par des points).
  2. Indiquez la clé adaptée à l'algorithme du header :
    • Pour HS256, HS384 ou HS512, la clé est la chaîne secrète partagée avec l'émetteur. C'est une chaîne libre, souvent stockée dans une variable d'environnement comme JWT_SECRET.
    • Pour RS256, RS384 ou RS512, la clé est la clé publique au format PEM, qui commence par -----BEGIN PUBLIC KEY----- et se termine par -----END PUBLIC KEY-----.
  3. Lancez la vérification. L'outil affiche le statut (valide ou invalide) et le payload décodé.

Pièges courants à éviter

  • Algorithme "none" : la spec autorise alg: none, qui signifie "pas de signature". Une faille classique consiste à fabriquer un token avec ce header en espérant que le serveur l'accepte. Notre outil rejette systématiquement les tokens avec alg: none.
  • Confusion HMAC vs RSA (algorithm confusion) : un attaquant change l'algorithme RS256 en HS256 et signe le payload avec la clé publique RSA utilisée comme secret HMAC. Si le serveur ne contrôle pas l'algorithme, il accepte le token. Toujours verrouiller l'algorithme attendu côté serveur.
  • Secrets HMAC en dur dans le code : un secret committé dans un dépôt Git rend toute la confiance des tokens caduque. Stockez les secrets dans des variables d'environnement ou un coffre-fort applicatif.
  • Clé publique vs clé privée : pour vérifier un JWT signé en RSA ou ECDSA, on fournit la clé publique, jamais la privée. La privée ne sert qu'à signer et ne doit jamais sortir de l'émetteur.
  • Expiration ignorée : une signature valide sur un token expiré ne doit jamais être acceptée. Pensez à vérifier exp et nbf.
  • Audience non contrôlée : un token destiné à l'API A ne devrait pas être accepté par l'API B. Vérifiez le claim aud.

Claims temporels : exp et nbf

Au-delà de la signature, un JWT valide doit aussi respecter ses contraintes temporelles :

  • exp (expiration) : le token n'est plus valide après cette date.
  • nbf (not before) : le token n'est pas encore valide avant cette date.

Notre outil signale explicitement quand un token est expiré ou pas encore valide, même si sa signature est correcte. C'est important : une signature valide sur un token expiré ne doit jamais être acceptée en production.

Différence avec notre JWT decoder

Notre JWT decoder se contente de décoder les parties header et payload pour les rendre lisibles. Il n'effectue aucune vérification de signature et ne demande pas de clé. Utilisez-le pour inspecter rapidement le contenu d'un token. Utilisez le JWT verifier (cette page) dès que vous avez besoin de prouver qu'un token est authentique. Pour fabriquer un JWT signé à des fins de test, utilisez notre JWT builder.

Questions fréquentes

Pourquoi RS256 plutôt que HS256 ?

Avec HS256, l'émetteur et le vérificateur partagent le même secret : tout vérificateur peut donc émettre des tokens. C'est gérable quand on contrôle les deux bouts. Dès qu'on parle d'un fournisseur d'identité unique avec plusieurs services consommateurs, on bascule en RS256 : l'émetteur garde la clé privée, on distribue la clé publique à toutes les API qui doivent vérifier. Aucune API consommatrice ne peut alors forger de tokens.

Comment récupérer la clé publique d'un fournisseur d'identité (IdP) ?

La plupart des IdP exposent un endpoint JWKS standardisé (par exemple https://exemple.com/.well-known/jwks.json). Cet endpoint renvoie un JSON contenant les clés publiques actives. Vous pouvez convertir l'entrée JWK qui correspond au kid du header de votre JWT en clé PEM via la commande openssl ou via une bibliothèque JWKS de votre stack (par exemple jose-jwt, jwks-rsa).

Que faire si le verify échoue ?

Vérifiez d'abord l'algorithme : un token signé en HS256 ne se vérifie pas avec une clé RSA, et inversement. Vérifiez ensuite la clé : un caractère blanc en trop, un retour à la ligne manquant dans une clé PEM, ou un secret HMAC légèrement différent de celui utilisé par l'émetteur suffisent à faire échouer la vérification. Si l'IdP a effectué une rotation de clé, votre kid peut pointer vers une clé que vous n'avez plus.

JWKS, c'est quoi ?

JWKS (JSON Web Key Set, RFC 7517) est un format JSON qui décrit un ensemble de clés publiques. Chaque clé est identifiée par un kid (key ID) et le JWT à vérifier référence ce kid dans son header. Le mécanisme permet à l'IdP de faire tourner ses clés sans casser les vérificateurs : ils interrogent simplement l'endpoint JWKS pour récupérer la clé correspondant au kid du token reçu.

Comment générer une paire de clés RSA pour signer mes JWT ?

Avec OpenSSL : openssl genrsa -out private.pem 2048 puis openssl rsa -in private.pem -pubout -out public.pem. La clé privée signe côté émetteur, la clé publique vérifie côté consommateur. Pour de nouveaux services, préférez 3072 ou 4096 bits.

Faut-il chiffrer le JWT en plus de le signer (JWE) ?

Un JWT signé (JWS) garantit l'intégrité et l'authenticité, mais le payload reste lisible par quiconque le récupère. Si le token contient des données sensibles (identifiants internes, droits détaillés, données personnelles), envisagez le format JWE (JSON Web Encryption) qui chiffre le payload en plus de le signer.

Exemple de requête

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

Schéma d'entrée

Champ Type Requis Défaut
token text
key 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-verifier - récupère le schéma de cet outil
  • POST https://cdrn.fr/api/v1/tools/jwt-verifier/execute - exécute cet outil avec un payload JSON