JWT が正しく decode でき、expired でもなく、signature も通るのに API が拒否するとき、私は aud を早い段階で server config と比較します。**Audience mismatch は「token 自体は正しくても、その recipient 向けではない」**ケースが多いからです。
API が期待する audience が分かっているなら JWT デバッガー で token の aud と直接比較します。
aud をどう読むか
RFC 7519 の Audience claim は「この token を受け取る想定の recipient」を表します。
1 audience:
{ "aud": "api://orders" }
複数 audiences:
{ "aud": ["api://orders", "api://reporting"] }
resource server が intended recipient に含まれないなら、token を reject するのが正しい動作です。
最初に expected と actual を並べる
Expected by API: api://orders
Token aud: api://billing
私はここで「API を permissive にしよう」と考えません。client がなぜ別 resource 用 token を取得したのかを逆方向に追います。
JWT デコーダー で raw aud を読み、API / gateway の configured audience と exact value を比較します。
よくある原因 1: wrong resource を request している
login 自体が成功していても、authorization request が Billing resource を対象にし、その token で Orders API を呼べば mismatch します。
この場合 JWT を編集せず、OAuth resource / scope / audience parameter、または IdP application config を確認します。
よくある原因 2: dev / staging / production の混在
API expects: api://orders-prod
Token aud: api://orders-dev
のような違いは非常によくあります。
このとき私は iss も同時に見ます。issuer と audience の両方が dev を指すなら、異なる実行環境という診断が強くなります。
環境変数、IdP application ID、gateway config、client が request した resource identifier を確認します。
よくある原因 3: token type が違う
OIDC の ID token を API に送っているケースです。
ID token は主に client application 向けで、その aud が client ID を示すことがあります。resource server は普通、その API 向け access token を期待します。
aud が frontend client ID に見え、API scope もないなら、Authorization header に wrong token variable が入っていないか確認します。
JWT という形だけで interchangeability を判断しません。
aud が array の場合
validator が scalar string しか想定していないと false mismatch が起こります。
{
"aud": ["api://orders", "api://reporting"]
}
を正しく扱い、対象 API が token profile のルールに従って audience set に含まれるかを見ます。
audience validation を disable しない理由
1 issuer が複数 API 向け token を発行する環境で audience check を外すと、別 service 用 token が substitute される可能性があります。
RFC 8725 も複数 relying party / application があるとき audience validation を重視しています。
だから mismatch の修正は check を弱めることではなく、token acquisition または expected audience config を正しくすることです。
JWT 内の aud を編集して直さない
例えば:
{ "aud": "api://billing" }
を:
{ "aud": "api://orders" }
へ編集して再エンコードすると signed bytes が変わります。元の signature は通らなくなるべきです。
正しい修正は trusted issuer に正しい resource 用 token を発行してもらうことです。
issuer と audience を分けて考える
iss= 誰が発行したかaud= 誰向けか
trusted issuer の valid token でも wrong API 向けなら reject されます。issuer が正しいだけでは足りません。
両方おかしい場合は environment / tenant mismatch を先に疑います。
audience と scope / role も別問題
{
"aud": "api://orders",
"scope": "orders:read"
}
なら audience は正しくても orders:write operation は許可されない可能性があります。
まず authentication / audience が通ることを確認し、その後に authorization data を見ます。JWT claims ガイド で標準 claim と application-specific claim の見方を整理しています。
私の audience mismatch workflow
- JWT を decode して
audをそのまま読む。 - 実際に failure を返した API を確認する。
- その API が accept する exact audience/resource を確認する。
- expected / actual を勝手に normalize せず比較する。
- dev/staging/prod と tenant config を確認する。
- client がこの API 向け access token を送っているか確認する。
- string / array の
audを正しく扱う。 issも trusted issuer と比較する。- issuer に bind された key で signature を verify する。
- JWT を編集せず token acquisition / API config を直す。
より広い authentication failure なら JWT 401 troubleshooting に進みます。
私がこの error から覚えておくのは、token が authentic でも、すべての recipient に適切とは限らないということです。