Mensaje de error
Signed JWT rejected: Invalid signature
También se muestra como
- com.nimbusds.jose.proc.BadJWSException: Signed JWT rejected: Invalid signature
- org.springframework.security.oauth2.jwt.BadJwtException: An error occurred while attempting to decode the Jwt: Signed JWT rejected: Invalid signature
Nimbus JOSE + JWT (Java) — BadJWSException from DefaultJWTProcessor; also surfaced by Spring Security's NimbusJwtDecoder
Qué significa
Nimbus seleccionó una o varias claves candidatas para el token (por `kid`, `alg` y tipo de clave) y ninguna de ellas verificó la firma. La selección funcionó —de lo contrario verías «Another algorithm expected, or no matching key(s) found»—, así que las claves en las que confías y la clave que firmó el token son distintas, o el token se modificó. Spring Security informa de la misma situación a través de `NimbusJwtDecoder`, con el prefijo «An error occurred while attempting to decode the Jwt:».
Por qué ocurre
Mismo kid, clave distinta
frecuenteLos ID de clave como `default`, `rsa1` o una fecha se reutilizan cuando se regenera una clave (por entorno, por despliegue, tras perder la clave antigua). El verificador encuentra una clave con el `kid` correcto que nunca firmó el token.
El servidor de recursos confía en las claves de otro emisor
frecuenteUn `jwk-set-uri` que apunta a un realm, un inquilino (tenant) o un entorno distinto del que emite los tokens.
El secreto HMAC difiere entre servicios
ocasionalCon HS256 y un `MACVerifier`, cualquier diferencia en los bytes del secreto compartido (codificación, salto de línea final) hace que todas las firmas sean no válidas.
El token se modificó después de firmarlo
ocasionalUn encabezado o una carga útil que un proxy volvió a codificar, o un token montado con partes de tokens distintos.
Cómo solucionarlo
- 1.
Configurar el emisor, no un conjunto de claves copiado a mano
Con `issuer-uri`, Spring Security lee `jwks_uri` del documento de descubrimiento del emisor y además valida `iss`.
yaml # Spring Boot resource server: derive the JWK Set from the issuer's discovery document spring: security: oauth2: resourceserver: jwt: issuer-uri: https://issuer.example.com/realms/main - 2.
Comparar huellas digitales, no solo valores kid
Las huellas digitales del RFC 7638 identifican el material de clave real. Si la huella digital de la clave publicada difiere de la de la clave con la que firma el emisor, el `kid` se está reutilizando.
java SignedJWT jwt = SignedJWT.parse(token); System.out.println(jwt.getHeader().getKeyID() + " " + jwt.getHeader().getAlgorithm()); JWKSet set = JWKSet.load(new java.net.URI("https://issuer.example.com/.well-known/jwks.json").toURL()); for (JWK key : set.getKeys()) { System.out.println(key.getKeyID() + " " + key.getAlgorithm() + " thumbprint=" + key.computeThumbprint()); }