エラーメッセージ
no applicable key found in the JSON Web Key Set
jose (JavaScript) — JWKSNoMatchingKey, code ERR_JWKS_NO_MATCHING_KEY
このエラーの意味
jose は渡された鍵セット(JSON Web Key Set)を調べましたが、このトークンの検証に使ってよい鍵が見つかりませんでした。鍵が対象になるのは、次の条件をすべて満たす場合だけです。`kid` がトークンのヘッダーの `kid` と等しいこと(トークンにある場合)、`kty` がトークンの `alg` に適合すること、`alg`(ある場合)がトークンの `alg` と等しいこと、`crv` が一致すること(ES256 なら P-256)、`use` がないか `"sig"` であること、`key_ops`(ある場合)に `"verify"` が含まれていること。暗号処理は一切実行されておらず、失敗したのは鍵の選択の段階です。
発生する理由
発行者が署名鍵をローテーションした
よくある新しいトークンには、キャッシュされた鍵セットやハードコードされた鍵セットにまだ含まれていない新しい `kid` が付いています。これは最もよくある原因で、たいていはローテーションが行われたまさにその時刻から発生します。その後に再起動したサービスは動作し、それ以前から動き続けているサービスは失敗します。
鍵セットが別の発行者や環境のもの
よくある本番環境で使われているステージングの JWKS URL、別のテナントの JWKS、ドキュメントからコピーした鍵セットなどです。どの `kid` ももっともらしく見えますが、一致するものはありません。
鍵のメタデータがトークンと矛盾している
ときどきトークンは ES256 なのに JWK が `alg: "RS256"` を持っている、あるいはトークンが ES256(P-256 が必要)を使っているのに EC 鍵の曲線が P-384 である、といった場合です。`kid` が一致していても、jose はこのような鍵をスキップします。JWK のメタデータは、まさに鍵が別のアルゴリズムに使われるのを防ぐために存在するからです。
鍵が暗号化用として指定されている
ときどき`use: "enc"` 付きで公開された鍵や、`"verify"` を含まない `key_ops` を持つ鍵は、署名検証鍵ではありません。プロバイダーによっては、両方の種類を 1 つの鍵セットで公開しています。トークンを検証できるのは `sig` の鍵だけです。
JWKS のローカルコピーが一度も更新されていない
ときどき`createLocalJWKSet` は、渡された鍵をいつまでも使い続けます。デプロイ時にファイルや環境変数から鍵セットを読み込んだ場合、次のローテーションで気づかないうちに古くなります。
修正方法
- 1.
トークンの kid を公開されている鍵と比較する
保護ヘッダーをデコードし、公開されている鍵を `kid`、`alg`、`kty`、`crv`、`use` とともに一覧表示してください。`kid` が鍵セットにない場合は、ローテーションか鍵セットの取り違えです。ある場合は、メタデータのフィールドを確認してください。
bash # kid and alg the token asks for python3 -c 'import base64,json,sys; h=sys.argv[1].split(".")[0]; print(json.loads(base64.urlsafe_b64decode(h + "=" * (-len(h) % 4))))' "$TOKEN" # kid, alg, kty, crv, use of every key the issuer publishes curl -s https://issuer.example.com/.well-known/jwks.json | jq '.keys[] | {kid, alg, kty, crv, use}' - 2.
鍵を固定せずに発行者の JWKS を取得する
`createRemoteJWKSet` は鍵をキャッシュし、まだ見たことのない `kid` を指定したトークンが来ると鍵セットを取得し直します。そのため、任意の鍵を受け入れることなく、ローテーションが自動的に反映されます。
js import { createRemoteJWKSet, jwtVerify } from "jose"; // Fetches the JWKS, caches it, and refetches when a token names an unknown kid // (at most once per cooldownDuration, 30 s by default). const jwks = createRemoteJWKSet(new URL("https://issuer.example.com/.well-known/jwks.json")); const { payload } = await jwtVerify(token, jwks, { algorithms: ["ES256"], issuer: "https://issuer.example.com", }); - 3.
矛盾のないメタデータを付けて鍵を公開する
発行者を自分で運用している場合は、各署名鍵に一意の `kid`、`use: "sig"`、その鍵で署名するトークンに合った `alg` と `crv` があることを確認してください。新しい鍵は、それで署名を始める前に公開してください。
json { "keys": [ { "kty": "EC", "crv": "P-256", "kid": "2026-10", "use": "sig", "alg": "ES256", "x": "…", "y": "…" } ] }
関連するエラー
multiple matching keys found in the JSON Web Key Setjose (JavaScript)Unable to find a signing key that matches '2026-10-rotated'jwks-rsa (Node.js)IDX10503: Signature validation failed. The token's kid is: '2026-10', but did n…Microsoft.IdentityModel.JsonWebTokens / System.IdentityModel.Tokens.Jwt (.NET)signature verification failedjose (JavaScript)