跳到主要内容
ecdsa.com
Nimbus JOSE + JWT (Java)Java

错误信息

Signed JWT rejected: Invalid signature

也可能输出为

  • 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

含义

Nimbus 为这个令牌选出了一个或多个候选密钥(依据 `kid`、`alg` 和密钥类型),但用其中任何一个密钥验证签名都没有通过。选择这一步是成功的——否则你看到的会是“Another algorithm expected, or no matching key(s) found”——因此,要么你信任的密钥与签名该令牌的密钥不同,要么令牌被修改过。Spring Security 通过 `NimbusJwtDecoder` 报告同样的情况,并加上前缀“An error occurred while attempting to decode the Jwt:”。

原因

修复方法

  1. 1.

    配置颁发者,而不是手动复制的密钥集

    配置 `issuer-uri` 后,Spring Security 会从颁发者的发现文档中读取 `jwks_uri`,并同时校验 `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. 2.

    比较指纹,而不只是 kid

    RFC 7638 指纹标识的是实际的密钥材料。如果已发布密钥的指纹与颁发者签名所用密钥的指纹不同,说明 `kid` 被重复使用了。

    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());
    }

相关错误

浏览完整的签名错误库