本文へスキップ
ecdsa.com
jose (JavaScript)JWKS と鍵のディスカバリ

エラーメッセージ

multiple matching keys found in the JSON Web Key Set

jose (JavaScript) — JWKSMultipleMatchingKeys, code ERR_JWKS_MULTIPLE_MATCHING_KEYS

このエラーの意味

鍵セット(JSON Web Key Set)の中に、このトークンを検証できる鍵が複数あり、jose は推測で選ぶことを拒否しました。これは、トークンのヘッダーに `kid` がなく(または複数の鍵が同じ `kid` を共有しており)、鍵セットに種類と曲線が合う鍵が 2 つ以上含まれている場合に起こります。jose は意図的に、`jwtVerify` の内部で候補の鍵を代わりに試すことはしません。スローされるエラー自体が候補の鍵を順に返す非同期イテレーターになっているため、明示的にオプトインすれば候補を試せます。

発生する理由

修正方法

  1. 1.

    すべてのトークンで署名鍵を識別できるようにする

    確実な修正は発行者側で行います。各鍵に一意の `kid` を割り当て(RFC 7638 のサムプリントが適しています)、それを JWKS で公開し、すべてのトークンの保護ヘッダーに書き込んでください。

    js
    import { SignJWT } from "jose";
    
    // Issuer side: name the key in every token, and publish the same kid in the JWKS.
    const token = await new SignJWT(claims)
      .setProtectedHeader({ alg: "ES256", kid: "2026-10" })
      .setExpirationTime("10m")
      .sign(privateKey);
  2. 2.

    候補の鍵を順に試す処理を明示的に有効にする

    発行者を変更できない場合は、エラーを反復処理してください。jose は候補の鍵を 1 つずつ返すので、そのいずれかで検証に成功した場合にのみトークンを受け入れます。候補ごとに署名の検証が 1 回かかるため、鍵セットは小さく保ってください。

    js
    import { errors, jwtVerify } from "jose";
    
    async function verifyWithCandidates(token, jwks, options) {
      try {
        return await jwtVerify(token, jwks, options);
      } catch (err) {
        if (err?.code !== "ERR_JWKS_MULTIPLE_MATCHING_KEYS") throw err;
        for await (const publicKey of err) {
          try {
            return await jwtVerify(token, publicKey, options);
          } catch (inner) {
            if (inner?.code === "ERR_JWS_SIGNATURE_VERIFICATION_FAILED") continue;
            throw inner;
          }
        }
        throw new errors.JWSSignatureVerificationFailed();
      }
    }

関連するエラー

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