Message d’erreur
token signature is invalid: crypto/ecdsa: verification error
Également affiché sous la forme
- token signature is invalid: crypto/rsa: verification error
- token signature is invalid: signature is invalid
- token signature is invalid: ed25519: verification error
- crypto/ecdsa: verification error
golang-jwt v4 ne renvoie que le texte interne, par exemple « crypto/ecdsa: verification error ». Utilisez `errors.Is(err, jwt.ErrTokenSignatureInvalid)` (v5) plutôt que de comparer des chaînes.
golang-jwt/jwt (Go) — jwt.ErrTokenSignatureInvalid joined with the algorithm's verification error
Ce que cela signifie
golang-jwt a analysé le jeton, accepté son algorithme et obtenu une clé de votre `Keyfunc`, mais la signature ne se vérifie pas avec cette clé. En v5, l’erreur combine `jwt.ErrTokenSignatureInvalid` (« token signature is invalid ») avec l’erreur propre à l’algorithme : `crypto/ecdsa: verification error` pour ES*, `crypto/rsa: verification error` pour RS*/PS*, `signature is invalid` pour HS*. Les octets du jeton et la clé ne vont tout simplement pas ensemble.
Pourquoi cela se produit
La Keyfunc renvoie la mauvaise clé
fréquenteUne clé d’un autre environnement, une clé codée en dur copiée depuis la documentation, ou une Keyfunc qui ignore `kid` et renvoie toujours la première clé d’un jeu de clés qui en contient plusieurs.
L’émetteur a effectué une rotation de sa clé de signature
fréquenteLes services qui chargent une clé publique une seule fois au démarrage continuent de vérifier avec l’ancienne clé après une rotation. Chaque nouveau jeton échoue alors que les anciens jetons mis en cache passent encore, jusqu’à ce que le service recharge la clé.
Le signataire a produit une signature ECDSA encodée en DER
occasionnellegolang-jwt attend les signatures ES256 sous forme de 64 octets bruts (r‖s, RFC 7518). Un jeton signé par un KMS ou par `ecdsa.SignASN1` sans conversion porte une signature DER d’environ 71 octets, dont la vérification échoue même avec la bonne clé.
Le jeton a été modifié après la signature
occasionnelleCharges utiles réencodées, espaces modifiés dans le segment d’en-tête ou de charge utile, ou jeton assemblé à partir de morceaux de deux jetons différents. La signature porte sur le texte base64url exact.
Comment corriger l’erreur
- 1.
Résoudre la clé par kid à partir du JWKS
Laissez la Keyfunc choisir dans le jeu de clés de l’émetteur la clé désignée dans l’en-tête du jeton, et actualiser ce jeu lors des rotations (par exemple avec `github.com/MicahParks/keyfunc`). Fixez toujours `WithValidMethods`.
go import ( "context" "github.com/MicahParks/keyfunc/v3" "github.com/golang-jwt/jwt/v5" ) // Resolve the verification key from the issuer's JWKS by the token's kid. k, err := keyfunc.NewDefaultCtx(ctx, []string{"https://issuer.example.com/.well-known/jwks.json"}) if err != nil { return err } token, err := jwt.Parse(raw, k.Keyfunc, jwt.WithValidMethods([]string{"ES256"}), jwt.WithIssuer("https://issuer.example.com/"), jwt.WithAudience("https://api.example.com")) - 2.
Prouver que les deux côtés utilisent la même clé
Calculez, côté vérificateur, le condensat de la clé publique encodée en DER, puis celui de la moitié publique de la clé privée de l’émetteur. Des condensats différents mettent fin à l’enquête.
bash # Same key on both sides? Compare SPKI fingerprints. openssl pkey -pubin -in verifier-public.pem -outform DER | sha256sum openssl pkey -in issuer-private.pem -pubout -outform DER | sha256sum - 3.
Traiter la classe d’erreur, pas la chaîne
golang-jwt v5 expose des erreurs sentinelles. Convertissez un échec de signature en réponse 401, et ne vous rabattez ni sur l’essai d’autres clés ni sur l’omission de la vérification.
go switch { case errors.Is(err, jwt.ErrTokenSignatureInvalid): return http.StatusUnauthorized // wrong key or tampered token: never retry with another key blindly case errors.Is(err, jwt.ErrTokenExpired): return http.StatusUnauthorized // client should refresh case errors.Is(err, jwt.ErrTokenMalformed): return http.StatusBadRequest }