JWT header 的 kid 我會把它看成 在已信任 key set 裡尋找 candidate key 的 identifier,而不是「這把 key 已可信」的證明。
例如:
{
"alg": "RS256",
"kid": "2026-09-key-b"
}
真正的信任流程應該是:
configured issuer
→ trusted JWKS
→ 用 kid 選 candidate
→ 檢查 key/algorithm compatibility
→ signature verification
→ issuer/audience/time validation
為什麼需要 kid
issuer 可以同時公開多把 key,尤其 rotation 期間:
{
"keys": [
{ "kid": "old-key", "kty": "RSA", "...": "..." },
{ "kid": "new-key", "kty": "RSA", "...": "..." }
]
}
header 的 kid 幫 verifier 快速找到應嘗試的 key。
kid match 不等於 verification success
我找到同名 JWK 後,還會檢查:
- candidate 是否唯一;
kty是否符合 algorithm family;- JWK
alg若存在是否一致; use若存在是否是sig;key_ops若存在是否包含verify;- EC curve 是否相容。
最後還要真正驗 signature。JWKS Validator 會明確區分「找到 key」與「signature verified」。
Unknown kid 怎麼處理
rotation 後最常見:
JWT kid = new-key
cached JWKS = old-key only
我會先查 cache,找不到時做一次受控、rate-limited refresh,再找一次;還是沒有就 fail closed。
我不讓每個 random kid 都造成 unlimited network fetch,避免攻擊者製造 refresh storm。
完整 rotation 流程見 JWT Key Rotation。
Duplicate kid 怎麼處理
如果 JWKS 有多個相同 kid,又無法透過 kty/alg/use/key_ops 唯一選出 candidate,我會把它當 ambiguous configuration error。
不會因為 array 第一個剛好能驗就依賴 key ordering。
沒有 kid 一定 invalid 嗎
不一定。如果 trusted key set 只有一把 compatible key,某些 verifier 可以明確選出它。但在多 key 與 rotation 環境,kid 能大幅降低 ambiguity。
我會為未來 rotation 設計,而不是只看今天 JWKS 只有一把 key。
kid 是 untrusted string
因為它來自未驗證 header,我不會把 kid 直接串到:
- filesystem path;
- SQL query;
- shell command;
- 任意 URL。
我偏好在已取得的 trusted JWKS object 裡做 exact string lookup,並限制過長、control characters 或 path-like pattern。
JWT Security Analyzer 也會對可疑 kid 提示 policy signal。
kid 與 jku 是不同概念
kid 用來選 key;jku 可以指向 remote JWK Set URL。
我避免:
JWT 給 jku
→ verifier 自動 fetch
→ 用 kid 找 key
→ 接受 token
因為這會讓 token 選自己的 key source。
我會從 trusted issuer metadata 決定 JWKS,再使用 kid。
Rotation 時我不重用舊 kid
new key material 如果重用 old kid,stale cache 可能仍指向舊 public key,造成難解的 invalid signature。
我通常為 new key 使用 new kid。JWK Inspector 的 RFC 7638 thumbprint 可用來確認兩份 JWK 的核心 public key material 是否相同。
kid 和 invalid signature 的排查順序
- 讀 token
kid; - 確認 expected issuer;
- 取得該 issuer 的 trusted JWKS;
- 計算 matching candidates;
- 檢查 key metadata compatibility;
- 實際驗 signature;
- 看 JWKS cache / rotation 是否 stale。
更完整 signature 排查可看 JWT Invalid Signature。
我會寫哪些測試
unique matching kid → candidate selected
unknown kid → controlled refresh / fail
duplicate kid → ambiguous fail
kid matches but wrong kty → fail
kid matches but wrong alg → fail
kid matches but signature wrong → fail
這能防止程式未來退化成「只要 kid 找得到就算 valid」。
我的 kid 清單
- 把
kid當 untrusted identifier。 - 先確定 trusted issuer/JWKS。
- 只在 trusted set 裡做 exact lookup。
- duplicate/ambiguity fail closed。
- 驗
kty、alg、use、key_ops、curve。 - 真正執行 signature verification。
- unknown kid refresh 需要 rate limit。
- rotation 時 new key 用 new
kid。 - 不把
kid直接當 path/query/URL。 - signature 後仍驗 issuer/audience/time。
我對 kid 最重要的理解是:它可以告訴 verifier「先試哪一把 key」,卻不能告訴 verifier「這把 key 為什麼值得信任」。 Trust 仍然來自 configured issuer、trusted key source 與真正的 signature verification。