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
- application が trust する issuer を確認する。
- issuer の trusted config / metadata から JWKS を得る。
kidは lookup hint として使う。- candidate JWK の
ktyを確認する。 alg/use/key_opsがあれば compatibility を確認する。- intended algorithm で key を import する。
- signature を verify する。
- その後で
iss、aud、exp、token type を validate する。
私の最短ルールは、JWK は key、JWKS は key ring、kid は ring から key を選ぶ hint です。そしてその key ring 自体が trusted issuer に結び付いていなければ意味がありません。