Fehlermeldung
Signature verification failed (JWT::VerificationError)
Auch ausgegeben als
- JWT::VerificationError: Signature verification failed
Wird die Ausnahme nicht abgefangen, gibt Ruby die Stelle des Fehlers aus, gefolgt von „Signature verification failed (JWT::VerificationError)“; der Text ist in ruby-jwt 2.10 und 3.3 derselbe.
ruby-jwt (Ruby) — JWT::VerificationError from JWT.decode
Was der Fehler bedeutet
ruby-jwt hat das Token dekodiert und seine Signatur mit dem Schlüssel geprüft, den du übergeben hast, und diese Prüfung ist fehlgeschlagen. Das Token ist wohlgeformt und der Algorithmus erlaubt; der Schlüssel gehört nicht zum Signierer, oder das Token wurde verändert. `JWT::VerificationError` ist eine Unterklasse von `JWT::DecodeError`, deshalb fängt `rescue JWT::DecodeError` ihn zusammen mit den Fehlern für nicht wohlgeformte Tokens ab.
Warum der Fehler auftritt
Der konfigurierte Schlüssel gehört nicht zum Signierer
häufigEin öffentlicher Schlüssel aus einer anderen Umgebung, ein veralteter Schlüssel nach einer Rotation oder ein Entwicklungs-Setup, das bei jedem Start ein neues Schlüsselpaar erzeugt und in die Produktion gelangt ist.
Prüfung mit dem falschen Schlüssel aus einem JWKS
gelegentlich`keys.first` aus dem JWKS eines Ausstellers zu nehmen funktioniert, bis der Aussteller mit einem anderen Schlüssel signiert. Lass ruby-jwt mit der Option `jwks:` anhand von `kid` auswählen.
Unterschiedliche HMAC-Secrets
gelegentlichRails-Anwendungen leiten das Secret oft aus `secret_key_base` ab; ein Dienst, der einen anderen Wert verwendet – oder denselben Wert mit einem abschließenden Zeilenumbruch –, berechnet einen anderen MAC.
So behebst du den Fehler
- 1.
Schlüssel anhand von kid aus dem JWKS des Ausstellers auswählen
Die Option `jwks:` akzeptiert einen Loader; ruby-jwt ruft diesen Loader erneut mit `kid_not_found: true` auf, wenn das Token einen unbekannten Schlüssel nennt, sodass Rotationen übernommen werden.
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.
Nachweisen, dass die Schlüssel übereinstimmen
Identische Hashes der öffentlichen Hälften schließen den Schlüssel als Ursache aus; suche dann nach Veränderungen des Tokens auf dem Übertragungsweg.
bash openssl pkey -in issuer-private.pem -pubout | sha256sum openssl pkey -pubin -in configured-public.pem | sha256sum # must be identical