Message d’erreur
Signature verification failed (JWT::VerificationError)
Également affiché sous la forme
- JWT::VerificationError: Signature verification failed
Si l’erreur n’est pas interceptée, Ruby affiche l’emplacement suivi de « Signature verification failed (JWT::VerificationError) » ; le texte est identique dans ruby-jwt 2.10 et 3.3.
ruby-jwt (Ruby) — JWT::VerificationError from JWT.decode
Ce que cela signifie
ruby-jwt a décodé le jeton et vérifié sa signature avec la clé que vous avez passée, et la vérification a échoué. Le jeton est bien formé et l’algorithme est autorisé ; soit la clé n’appartient pas au signataire, soit le jeton a été modifié. `JWT::VerificationError` est une sous-classe de `JWT::DecodeError` : `rescue JWT::DecodeError` l’intercepte donc en même temps que les erreurs de jeton mal formé.
Pourquoi cela se produit
La clé configurée n’est pas celle du signataire
fréquenteUne clé publique d’un autre environnement, une clé périmée après une rotation, ou une paire de clés régénérée à chaque démarrage dans une configuration de développement qui s’est retrouvée en production.
Vérification avec la mauvaise clé d’un JWKS
occasionnellePrendre `keys.first` dans le JWKS d’un émetteur fonctionne jusqu’à ce que l’émetteur signe avec une autre clé. Laissez ruby-jwt sélectionner la clé par `kid` avec l’option `jwks:`.
Des secrets HMAC différents
occasionnelleLes applications Rails dérivent souvent le secret de `secret_key_base` ; un service qui utilise une autre valeur (ou la même valeur suivie d’un saut de ligne final) calcule un MAC différent.
Comment corriger l’erreur
- 1.
Sélectionner les clés par kid dans le JWKS de l’émetteur
L’option `jwks:` accepte un chargeur ; ruby-jwt le rappelle avec `kid_not_found: true` lorsque le jeton désigne une clé inconnue, si bien que les rotations sont prises en compte.
ruby require "jwt" require "net/http" jwks_loader = ->(options) do @jwks = nil if options[:kid_not_found] && @jwks_loaded_at.to_i < Time.now.to_i - 300 # refetch on rotation @jwks ||= begin @jwks_loaded_at = Time.now.to_i JSON.parse(Net::HTTP.get(URI("https://issuer.example.com/.well-known/jwks.json"))) end end payload, header = JWT.decode(token, nil, true, algorithms: ["ES256"], jwks: jwks_loader, iss: "https://issuer.example.com/", verify_iss: true) - 2.
Prouver que les clés correspondent
Si les condensats des parties publiques sont identiques, la clé est hors de cause ; cherchez alors des modifications du jeton en transit.
bash openssl pkey -in issuer-private.pem -pubout | sha256sum openssl pkey -pubin -in configured-public.pem | sha256sum # must be identical