Pour invalid signature ou signature verification failed, je ne modifie ni payload ni configuration au hasard. Je conserve le compact JWT original puis j’isole algorithme, octets de clé, issuer, kid, JWKS et rotation.
Avec secret/public key connu, j’utilise JWT Signature Verifier ; avec JWKS, JWKS Validator.
Ce que signifie exactement invalid signature
Un JWS compact signe :
base64url(header).base64url(payload)
La vérification porte sur ces octets originaux. Un échec implique qu’algorithme, clé ou signed bytes ne correspondent pas au signer.
Cela ne signifie pas automatiquement token expiré, mauvaise audience ou permissions manquantes.
Je sépare immédiatement HMAC et RSA/EC
HS256/384/512 -> secret bytes / encoding / rotation
RS256/ES256 -> public key / kid / JWKS / issuer
La liste d’algorithmes autorisés vient de l’application, jamais du header non fiable.
HMAC : même texte visible, octets différents
Je vérifie :
- UTF-8 raw vs secret décodé Base64 ;
- newline dans une variable d’environnement ;
- secrets différents dev/prod ;
- rotation ;
- espaces de copier/coller ;
- secret trop faible.
const utf8 = new TextEncoder().encode(process.env.JWT_SECRET);
const b64 = Uint8Array.from(atob(process.env.JWT_SECRET), c => c.charCodeAt(0));
Ces deux clés peuvent être différentes.
RSA : format de clé et provenance
-----BEGIN PUBLIC KEY-----
-----BEGIN CERTIFICATE-----
-----BEGIN RSA PUBLIC KEY-----
SPKI, certificat X.509 et PKCS#1 ne sont pas interchangeables dans toutes les libraries. Je convertis explicitement.
kid, JWKS et rotation
Je recherche kid uniquement dans le JWKS de confiance de l’issuer attendu. Causes typiques :
- cache JWKS obsolète ;
- nouvelle clé non chargée ;
- ancienne clé retirée trop tôt ;
- mauvais tenant/issuer ;
ktyoualgincompatible ;kiddupliqué.
Voir JWT kid et key rotation.
Je distingue les messages par phase
JsonWebTokenError: invalid signature
JWSSignatureVerificationFailed
signature verification failed
kid not found
no applicable key found in the JSON Web Key Set
kid not found indique d’abord un échec de sélection, pas forcément une comparaison cryptographique ratée.
Je ne re-sérialise pas le payload
{"sub":"42","role":"user"}
et
{ "role": "user", "sub": "42" }
peuvent représenter les mêmes données mais pas les mêmes octets. La signature JWS couvre le compact input original.
Signature valide ≠ token acceptable
Après la signature, je valide encore :
exp/nbf;- expected
iss; - expected
aud; - token type ;
- scopes/roles.
J’utilise JWT Validator ou JWT Debugger.
Ce que je refuse comme « correctif »
- désactiver la signature ;
- accepter le
algchoisi par le token ; - faire confiance à une
jkuarbitraire ; - modifier le payload et garder la signature ;
- prendre la première clé JWKS ;
- affaiblir un secret HMAC pour simplifier la configuration.
Matrice de diagnostic
| Symptôme | Couche probable | Vérifier |
|---|---|---|
| HS256 invalid signature | secret/encoding | bytes, Base64, newline |
| RS256 invalid signature | public key | issuer, PEM/JWK |
kid not found | selection/cache | JWKS, rotation |
| algorithme non autorisé | policy | allowlist, key type |
| après édition payload | signed bytes | token original |
| signature ok + 401 | claims | exp/iss/aud/type |
Mon workflow déterministe
- Je garde le compact JWT original.
- Je lis
alg,kid,issavec JWT Decoder. - Je confirme les algorithmes permis par configuration.
- J’identifie la source de clé de confiance de l’issuer.
- En HMAC, je compare bytes/encoding exacts.
- En RSA/EC, je contrôle format, type et provenance.
- Avec JWKS, je vérifie
kid, cache et rotation. - Je vérifie le
header.payloadoriginal. - Ensuite je valide temps, issuer et audience.
- Je corrige key/config/deployment sans contourner la sécurité.
Invalid signature est un problème de confiance, pas un simple problème de parsing.
Je conserve les preuves minimales
Je note l’issuer attendu, le kid, l’algorithme, le type de clé et le composant qui a renvoyé l’erreur, sans recopier le JWT dans un ticket. Cette trace me permet de comparer un appel qui fonctionne avec un appel qui échoue et de déterminer si le problème vient de la sélection de clé, de la rotation ou de la configuration de vérification.