JWT 指南

我如何把 JWT issuer validation 當成信任鏈起點

我會把 iss 與 configured expected issuer 做 exact match,再將 issuer 綁定 metadata 與 JWKS,避免未驗證 token 自己決定 key source。

作者:JWTDecoder.tools最後確認 2026-09-13

編輯語氣說明:第一人稱敘述代表 JWTDecoder.tools 已文件化的驗證工作流程;發布者與組織作者皆為 JWTDecoder.tools。

expected iss === token iss
expected iss === token iss → issuer-bound JWKS

我驗 JWT 時,會把 iss 看成信任鏈的起點,而不是 payload 裡普通的一個字串。因為真正的問題是:我到底信任哪個 issuer,以及這個 issuer 對應哪一組 key?

iss 告訴我什麼

{
  "iss": "https://id.example.com/",
  "aud": "https://api.example.com"
}

這只代表 token 聲稱由這個 issuer 發行。token 還沒驗證前,我不會因為看到這個 URL 就自動信任它。

application config 應先知道:

expected issuer = https://id.example.com/

我使用 exact match

這兩個值可能不是同一個 issuer identifier:

https://id.example.com
https://id.example.com/

tenant path 也一樣:

https://id.example.com/tenant-a
https://id.example.com/tenant-b

我不會用 prefix、suffix 或隨意 trim 讓它們「差不多」。安全 identifier 應與 provider metadata / application config 精確一致。

我不讓 token 的 iss 自動建立 trust

我避免:

讀未驗證 JWT 的 iss
→ 自動 fetch 該 URL 的 metadata
→ 自動信任那裡的 JWKS
→ 驗 token

這樣等於讓 untrusted input 選擇自己的 trust source。

我使用:

configured issuer
→ token iss exact match
→ trusted metadata
→ trusted jwks_uri
→ key selection
→ signature verify

Metadata 回傳的 issuer 也要一致

OIDC/OAuth metadata 可能包含:

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

我會確認 returned issuer 和 discovery 使用的 issuer 精確一致。OIDC Discovery Checker 可以直接檢查這條關係。

Issuer 與 JWKS 要綁在一起

只找到一把能驗 signature 的 public key 不夠。我要知道這把 key 是否來自我信任的 issuer。

expected issuer
→ trusted metadata
→ trusted JWKS
→ kid candidate
→ signature verification

這可以避免把另一個 tenant/issuer 的 key 混進 verifier。

Multi-tenant 情況更需要清楚規則

一些 identity provider 有 tenant-specific issuer,也可能支援 multi-tenant。這時我會明確定義:

  • 哪些 tenant 可以接受;
  • expected issuer 如何形成;
  • metadata/JWKS 是否共用;
  • audience 是否也依 tenant/resource 不同。

我不只檢查 domain suffix。

Issuer 與 audience 是不同問題

  • iss:誰發的?
  • aud:發給誰?

兩者都要通過。signature 正確也不代表這兩項一定正確。

Audience 問題見 JWT Audience Mismatch。

Rotation 時 issuer binding 仍然不變

出現新 kid 時,我不會去網路上任意找 key。我只 refresh 該 trusted issuer 的 JWKS,再找新 key。

JWT Key Rotation 說明 unknown kid 與 cache refresh 的完整流程。

jku / x5u 不能取代 issuer policy

JWT header 可以帶 remote key URL,但我不會讓 token 自己指定任意 URL 當信任來源。key source 應由 configured issuer / metadata 決定。

我怎麼排查 issuer mismatch

  1. 用 JWT Decoder 看 raw iss。
  2. 找 server 真正 configured expected issuer。
  3. 比較 trailing slash、tenant path 等差異。
  4. 取得 trusted metadata,確認 returned issuer。
  5. 檢查 jwks_uri 是否屬於這條信任設定。
  6. 在該 JWKS 中選 kid candidate。
  7. 實際驗 signature。
  8. 再驗 audience 與 time claims。

JWKS Validator 可以同時輸入 expected issuer 重現這個流程。

我不採用的做法

  • 所有 issuer 都接受;
  • 只比 domain suffix;
  • token 說去哪裡抓 JWKS 就去哪裡;
  • signature 通過就忽略 issuer;
  • 為了消除 slash mismatch 而做過度 normalize。

我的 issuer validation 清單

  1. configured expected issuer 是明確值。
  2. token iss exact match。
  3. metadata returned issuer exact match。
  4. JWKS source 綁定 issuer。
  5. kid 只在 trusted set 裡選 key。
  6. 實際驗 signature。
  7. 再驗 audience、expiration、token type 與 permissions。

我重視 issuer validation,不只是要比較一個字串,而是要回答:這顆 JWT 的 cryptographic trust 到底屬於哪個身分系統、哪一組 key、哪個 security domain。

來源與參考資料

相關指南