本文へスキップ
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`、鍵の種類に基づいてトークンの候補となる鍵を 1 つ以上選択しましたが、どの鍵でも署名を検証できませんでした。鍵の選択には成功しています(失敗していれば「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());
    }

関連するエラー

署名エラーデータベースをすべて見る