Mensaje de error
Signature verification failed (JWT::VerificationError)
También se muestra como
- JWT::VerificationError: Signature verification failed
Si no se captura, Ruby imprime la ubicación seguida de «Signature verification failed (JWT::VerificationError)»; el texto es el mismo en ruby-jwt 2.10 y 3.3.
ruby-jwt (Ruby) — JWT::VerificationError from JWT.decode
Qué significa
ruby-jwt decodificó el token y comprobó su firma con la clave que le pasas, y la comprobación falló. El token está bien formado y el algoritmo está permitido: la clave no pertenece al firmante o el token se modificó. `JWT::VerificationError` es una subclase de `JWT::DecodeError`, así que `rescue JWT::DecodeError` lo captura junto con los errores de token mal formado.
Por qué ocurre
La clave configurada no es la del firmante
frecuenteUna clave pública de otro entorno, una clave desactualizada tras una rotación o un par de claves que se regenera en cada arranque en una configuración de desarrollo que acabó en producción.
Verificación con la clave equivocada de un JWKS
ocasionalTomar `keys.first` del JWKS de un emisor funciona hasta que el emisor firma con otra clave. Deja que ruby-jwt elija la clave por `kid` con la opción `jwks:`.
Secretos HMAC distintos
ocasionalLas aplicaciones Rails suelen derivar el secreto de `secret_key_base`; un servicio que usa otro valor —o el mismo valor con un salto de línea final— calcula un MAC distinto.
Cómo solucionarlo
- 1.
Seleccionar las claves del JWKS del emisor por kid
La opción `jwks:` acepta un cargador; ruby-jwt vuelve a llamarlo con `kid_not_found: true` cuando el token indica una clave desconocida, así que las rotaciones se tienen en cuenta.
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.
Demostrar que las claves coinciden
Si los hashes de las partes públicas son idénticos, la clave queda descartada como causa; entonces busca modificaciones del token en tránsito.
bash openssl pkey -in issuer-private.pem -pubout | sha256sum openssl pkey -pubin -in configured-public.pem | sha256sum # must be identical