JWT 指南

我如何排查 JWT audience mismatch

當 JWT 的 aud 與 API expected audience 不一致時,我會檢查 access token 與 ID token、單值/陣列 aud、環境設定、issuer 與 azp 規則,而不是直接關閉 audience validation。

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

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

token aud ∋ expected aud
token aud ∋ expected aud

看到 audience mismatch 時,我第一個問題不是「怎麼讓 verifier 不檢查 aud」,而是:這個 token 本來就是發給目前這個 API 的嗎? aud 是 JWT 用來表達 intended audience 的 claim,signature 正確也不能取代 audience validation。

aud 可以是字串,也可以是陣列

單一 audience:

{ "aud": "https://api.example.com" }

多個 audience:

{
  "aud": [
    "https://api.example.com",
    "secondary-service"
  ]
}

因此 verifier 應檢查 expected audience 是否存在於 aud,而不是假設它永遠只有 string。

我最先檢查四件事

  1. 送到 API 的是不是 access token?
  2. token 的 aud 是否包含目前 API?
  3. API 的 expected audience 是否屬於現在這個環境?
  4. issuer 是否真的被設定為發出這個 API 的 token?

大部分 audience mismatch 都能在這四個問題裡找到方向。

ID token 與 access token 最容易混淆

兩者都可能長成 JWT。ID token 的 aud 通常和 OIDC client 有關,而 resource API 往往期待自己的 resource identifier。

例如 token:

{ "aud": "web-client-id" }

API 設定:

expected audience = https://api.example.com

這時即使 signature 正常,API 拒絕它也是合理的。

我不會因為「這是一個 JWT」就認為它是可用的 access token。

環境設定很常是根因

我會比較:

local      → api://local
staging    → api://staging
production → api://production

如果 frontend 拿的是 staging token,卻打 production API,audience mismatch 正是應該發生的保護。

我會同時檢查 client 取得 token 時指定的 resource/audience,以及 server verifier 的 expected audience。

我不隨便 normalize audience

這兩個字串可能不同:

https://api.example.com
https://api.example.com/

我不會只為了讓 validation 通過就自動去掉 slash、忽略大小寫或做 prefix match。應該讓 identity provider 與 API 使用一致的 canonical identifier。

Signature valid 仍然可以 audience invalid

我會把這兩步分開:

trusted key 驗 signature
→ token 的完整性/簽發者 key

expected audience check
→ 這個 token 是否真的給我這個 resource

JWKS Validator 可以同時提供 expected audience,重現 signature 與 claim policy。

azp 不是通用替代品

在特定 OIDC 情況,尤其多 audience ID Token,azp(authorized party)有定義好的用途。但我不會在 aud mismatch 時隨便改用 azp 讓 token 通過。

只有 protocol/profile 明確要求時,我才依規則驗證 azp。

401 時不要只盯著 audience

很多 API 會把 audience mismatch 回成 401 Unauthorized,但 401 也可能是:

  • token 沒有送到;
  • expired/not-yet-valid;
  • signature fail;
  • issuer mismatch;
  • wrong token type;
  • scope/role 不足。

我會依 JWT 401 Unauthorized 的順序完整排查。

我如何寫 audience test

至少準備:

correct aud string → pass
wrong aud → fail
aud array contains expected → pass
aud array missing expected → fail
missing aud → 依 policy fail

signature 與 issuer 保持一致,才能單獨驗證 audience policy。

我不採用的修法

  • 關閉 audience validation;
  • aud 不存在也一律放行;
  • production 同時接受 local/staging/prod 全部 audience;
  • 用未定義 custom claim 代替 aud;
  • 只要 signature 正確就忽略 resource boundary。

我的 audience mismatch 清單

  1. 用 JWT Decoder 看 raw aud。
  2. 確認 token type 是正確 access token。
  3. 確認 aud 是 string 還是 array。
  4. 找到 API 真正 configured expected audience。
  5. exact comparison,不做危險的模糊匹配。
  6. 檢查 local/staging/prod 是否混用。
  7. 確認 signature 與 issuer validation 也各自通過。
  8. 只在 protocol 明確要求時處理 azp。

我最後只問一件事:這個 token 是否真的被發給目前這個 API? 如果不是,audience mismatch 就不是 bug,而是 verifier 正在正確地阻止跨 resource 使用 token。

來源與參考資料

相關指南