JWT ガイド

JWK と JWKS を JWT 検証でどう使い分けるか

単一 JWK と JWKS の違い、kid による key selection、jwks_uri、key rotation、署名検証までを実務の trust chain に沿って説明します。

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

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

信頼済み issuer、JWKS、kid、JWK の関係図
信頼済み issuer の JWKS 内で kid が JWK を選択し、その鍵で署名を検証します。

JWK と JWKS が同じ documentation に出てくるとき、私は最初に次の 1 行へ整理します。

JWK は 1 個の cryptographic key を JSON で表したもの。JWKS は複数 JWK を入れる key set。

違いは単純ですが、kid、key rotation、複数 signing key、jwks_uri を扱い始めると重要になります。

JWT と key set が手元にあるなら JWKS Validator で、kid → compatible JWK → signature verification の流れを確認できます。

JWK は「1 つの key」

RFC 7517 の JSON Web Key は cryptographic key を表す JSON object です。RSA public JWK は例えば:

{
  "kty": "RSA",
  "kid": "signing-key-2026-09",
  "use": "sig",
  "alg": "RS256",
  "n": "...",
  "e": "AQAB"
}

私は主に次を見ます。

  • kty — key type。
  • kid — key identifier。
  • use — sig / enc など大きな用途。
  • key_ops — verify など許可 operation。
  • alg — 意図する algorithm が明示されているか。
  • RSA の n/e、EC の crv/x/y など実際の key material。

JSON として正しい JWK だから trusted key になるわけではありません。

JWKS は keys[] を持つ key set

{
  "keys": [
    {
      "kty": "RSA",
      "kid": "key-old",
      "use": "sig",
      "alg": "RS256",
      "n": "...",
      "e": "AQAB"
    },
    {
      "kty": "RSA",
      "kid": "key-new",
      "use": "sig",
      "alg": "RS256",
      "n": "...",
      "e": "AQAB"
    }
  ]
}

実務ではこの JWK Set を JWKS と呼ぶことが多いです。

JWK  = 1 key
JWKS = key の集合

なぜ実際の JWT 検証では JWKS が多いのか

identity system は key を永遠に 1 個だけ使うとは限りません。

  • key rotation
  • old/new key の overlap
  • 複数 algorithm / key type
  • rollout 中の複数 signing key

に対応するため、issuer は複数 public key を JWKS で公開できます。

token header の kid は、どの候補 key を選ぶかの hint になります。

{
  "alg": "RS256",
  "kid": "key-new"
}

kid で key を選ぶときの流れ

私は次の順番にします。

JWT header kid
      ↓
trusted JWKS
      ↓
exact kid match
      ↓
kty / alg / use / key_ops compatibility
      ↓
key import
      ↓
signature verify

kid が一致しただけでは止まりません。例えば use: "enc" の key を signature verification に流用しません。

kid が missing / not found / duplicate のときは JWT kid ガイド の順番で調査します。

単一 JWK を使う場面

  • trusted JWKS から exact key を選び終えた後。
  • configuration が 1 個の public key を JSON で保持するとき。
  • Web Crypto / JOSE library に 1 key を import するとき。
  • 特定 RSA / EC key の metadata を調べるとき。

Web Crypto なら compatible JWK を直接 import できます。

const publicKey = await crypto.subtle.importKey(
  "jwk",
  jwk,
  { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" },
  false,
  ["verify"]
);

重要なのは、その JWK を trusted source から選んだかです。

JWKS 全体を保持する場面

まだ key selection が必要なら full set を使います。

  • issuer が rotation する。
  • token ごとに kid が違う。
  • unknown kid で controlled refresh したい。
  • old/new keys を比較したい。
  • resource server が継続的に token を verify する。

planned rotation で old/new JWK が同時に必要になる理由は JWT key rotation ガイド で詳しく扱っています。

jwks_uri をどう信頼するか

RFC 8414 の authorization-server metadata では jwks_uri が public JWK Set の URL になります。

{
  "issuer": "https://login.example.com/",
  "jwks_uri": "https://login.example.com/.well-known/jwks.json"
}

私が欲しい trust chain は:

configured issuer
      ↓
trusted metadata
      ↓
jwks_uri
      ↓
JWKS
      ↓
JWK selected by kid

逆に「JWT header が URL を書いているからそこを信頼する」という流れにはしません。token 自体は untrusted input だからです。

JWK と PEM は競合する概念ではない

同じ RSA public key を PEM で持つことも JWK で持つこともできます。

-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----

Browser Web Crypto は JWK と相性が良く、server library は PEM をよく受け取り、identity provider は JWKS で公開することが多いです。

format が変わっても trust decision は同じです。

use / key_ops / alg を確認する

JWK に次があるなら semantic compatibility を確認します。

{
  "use": "sig",
  "key_ops": ["verify"],
  "alg": "RS256"
}

これらは optional な場合もありますが、明示されているのに operation と矛盾する key は選びません。

rotation で違いが見えやすい

rotation 前:

JWKS
└── JWK A

planned overlap:

JWKS
├── JWK A (old)
└── JWK B (new)

old token の acceptance window が終わった後:

JWKS
└── JWK B

ただし compromise による emergency revocation なら old key を早く remove する判断もあります。rotation の目的まで含めて考えます。

私の trust checklist

  1. application が trust する issuer を確認する。
  2. issuer の trusted config / metadata から JWKS を得る。
  3. kid は lookup hint として使う。
  4. candidate JWK の kty を確認する。
  5. alg / use / key_ops があれば compatibility を確認する。
  6. intended algorithm で key を import する。
  7. signature を verify する。
  8. その後で iss、aud、exp、token type を validate する。

私の最短ルールは、JWK は key、JWKS は key ring、kid は ring から key を選ぶ hint です。そしてその key ring 自体が trusted issuer に結び付いていなければ意味がありません。

出典・参考資料

関連ガイド