JWT ガイド

JWT kid と JWKS のキー選択をデバッグする方法

kid not found、kid がない場合、古い JWKS cache、key rotation、algorithm の不整合を順に確認し、kid を信頼の証拠と混同しないための手順です。

著者: JWTDecoder.tools最終確認 2026-09-13

編集上の表現について:一人称の記述は JWTDecoder.tools の検証済みワークフローを示すもので、発行者・組織著者は JWTDecoder.tools です。

kid + alg → compatible JWK
trusted issuer → JWKS → kid + alg → JWK

kid not found、不明な key ID、key rotation 後の署名エラーを見たとき、私は payload より先に protected header を見ます。kid は信頼済み JWK Set から候補 key を選ぶための identifier だからです。

ただし目標は「何でもいいから verify させる」ことではありません。正しい issuer が管理する key set から、application が許可した algorithm に適合する key を選んだと説明できることが重要です。

JWT と JWKS があるなら JWKS Validator で alg / kid / iss と正確な key match を確認します。

Step 1: header の kid を読む

{
  "alg": "RS256",
  "typ": "JWT",
  "kid": "2026-09-key-03"
}

RFC 7515 / RFC 7517 の kid は Key ID です。JWK Set の中から特定の key を選ぶとき、特に rollover で役立ちます。

しかし kid は key selection の手掛かりです。信頼済み key であることの証明ではありません。未検証 token は好きな kid を書けます。

Step 2: 任意の key source ではなく、信頼する JWKS を見る

{
  "keys": [
    { "kty": "RSA", "kid": "2026-09-key-03", "use": "sig", "alg": "RS256", "n": "...", "e": "AQAB" },
    { "kty": "RSA", "kid": "2026-06-key-02", "use": "sig", "alg": "RS256", "n": "...", "e": "AQAB" }
  ]
}

私は application が信頼する issuer の JWKS 内で exact kid match を探します。

web 全体で同じ key ID を検索しません。kid は global に一意ではなく、同じ label の public key を見つけても trust は確立しません。

OAuth / OIDC の metadata を使うなら信頼経路は:

configured issuer
      ↓
trusted metadata
      ↓
trusted jwks_uri
      ↓
JWK Set
      ↓
kid match

です。

Step 3: kid がない場合

すべての signed JWT に kid が必須ではありません。

信頼する JWKS に compatible signing key が 1 個だけなら、verifier policy で一意に選べる場合があります。

しかし:

{
  "keys": [
    { "kty": "RSA", "kid": "key-a", "alg": "RS256" },
    { "kty": "RSA", "kid": "key-b", "alg": "RS256" }
  ]
}

で token header が:

{ "alg": "RS256" }

だけなら、明確な rule なしに「全部試して通ったものを使う」という実装を避けます。

JWKS Validator も複数の compatible key が残れば ambiguous と扱います。

Step 4: alg / kty / use / key_ops

kid match 後も次を確認します。

  • JWT alg
  • JWK kty
  • JWK alg があれば一致
  • JWK use があれば sig
  • JWK key_ops があれば verify

RS256 なら RSA verification key、ES256 なら P-256 EC key など、algorithm family と key type の compatibility が必要です。

application は algorithm allowlist を持ち、token の alg を policy として無条件に採用しません。

Step 5: kid not found なら rotation を確認する

典型的な流れ:

issuer publishes key A
      ↓
A で token を sign
      ↓
issuer introduces key B
      ↓
new token uses kid B
      ↓
verifier still caches only A

すると kid B not found になります。

私は:

  1. issuer が current JWKS に B を publish しているか。
  2. verifier の cache TTL。
  3. missing kid で controlled refresh するか。
  4. dev/old tenant の JWKS を見ていないか。

を確認します。

毎 request で network fetch するのではなく、controlled cache / refresh strategy を使います。

Step 6: environment / tenant の取り違え

JWT iss:    https://login.dev.example.com/
API trusts: https://login.example.com/

なら key set が違うのは自然です。

kid not found を見たとき「この key はどこ?」だけでなく「この token はそもそも想定 issuer / environment から来たか?」と確認します。

issuer validation ガイド と一緒に見る理由です。

Step 7: jku / x5u を自動で信頼しない

JOSE header の URL は token-controlled input です。

RFC 8725 は arbitrary URL follow による SSRF / trust failure を警告しています。

malicious token
→ attacker URL を key source として指定
→ server が fetch
→ attacker's key を trust

という流れにはしません。

JWKS Validator も jku / x5u を自動 follow せず、ユーザーが明示した JWKS URL だけを fetch します。

Step 8: kid matched と signature verified を分ける

kid found            ✓
algorithm compatible ✓
key intended for sig ✓
signature verified   ✓ / ✕

最初の 3 つが通っても cryptographic verification は別です。failure なら invalid signature ガイド に進みます。

Step 9: signature 後も claims を validate

signature が通った後に:

  • iss
  • aud
  • exp
  • nbf
  • token type/profile
  • scopes / roles

を確認します。

cryptographically valid な token でも current resource server 向けとは限りません。

私の kid debugging checklist

  1. JWT を decode して alg / kid / iss を読む。
  2. trusted issuer を決める。
  3. その issuer の trusted JWKS を得る。
  4. exact kid match を探す。
  5. kty / alg / use / key_ops を確認する。
  6. missing key なら rotation / cache を調べる。
  7. dev/prod / tenant の取り違えを調べる。
  8. token が指定する任意の鍵 URL を trust しない。
  9. selected JWK で signature を verify する。
  10. issuer / audience / time claims を続けて validate する。

私が最後まで守る考え方は、kid は key を見つけるための手掛かりであって、その key を trust すべき理由ではないということです。

出典・参考資料

関連ガイド