JWT の構造は正しいのに invalid issuer / issuer mismatch、あるいは署名検証後も 401 になるとき、私は iss を単なる format problem ではなく、信頼境界の問題として扱います。
知りたいのは単に「iss に何と書いてあるか」ではありません。
application がその issuer を信頼するよう設定されていて、verification に使った key が本当にその issuer に属しているか?
です。
期待する issuer が分かっているなら JWT デバッガー / JWKS Validator から始めます。
Step 1: iss を decode するが、まだ trust しない
{
"iss": "https://login.example.com/",
"sub": "user_123",
"aud": "api://orders",
"exp": 1789203600
}
RFC 7519 の iss は issuer identifier です。しかし signature verification 前なら attacker が任意の URL を payload に書けます。
「見慣れた URL だから安全」とは判断しません。
Step 2: application が期待する issuer を確認する
resource server の config から authoritative value を 1 つ特定します。
https://login.example.com/
似ていても別 identifier の可能性があります。
https://login.example.com
https://login.example.com/
https://login.example.com/tenant-a
https://login.example.com/tenant-b
library / protocol が exact match を要求するなら勝手に normalize しません。
configured issuer が間違っているなら token を編集せず application / IdP config を直します。
Step 3: dev / staging / prod の取り違えを探す
{
"iss": "https://login.dev.example.com/",
"aud": "api://orders-dev"
}
を production が受け取ると:
- issuer mismatch
- audience mismatch
kidnot found- signature failure
- production 用 scope がない
といった問題が同時に出ることがあります。
kid not found と issuer mismatch が一緒なら、crypto code より environment を先に見ます。
Step 4: trusted key set を issuer に結び付ける
RFC 8414 metadata の issuer と jwks_uri を使う場合、欲しい trust path は:
application trusts issuer A
↓
issuer A metadata
↓
issuer A jwks_uri
↓
key selected from issuer A JWKS
↓
signature verified
逆に、未検証の iss や token-provided URL から任意の key を trust する流れにはしません。
JWKS Validator が token の jku / x5u を自動 follow しないのもこの boundary のためです。
Step 5: signature を verify してから issuer-dependent claim を trust する
RS256 header に:
{ "kid": "prod-key-2026-09" }
があるなら、信頼する issuer の JWKS から kid を選び signature を verify します。
key が見つからなければ JWT kid ガイド、key はあるのに failure なら invalid signature ガイド に進みます。
issuer の設定が信頼する key source を決め、その key が signed iss を authenticate します。この 2 つは相互に関係しています。
Step 6: valid signature でも iss mismatch は reject する
signature verified with issuer A key ✓
iss == configured issuer A ✓
が理想です。
signature verified ✓
iss == configured issuer ✕
なら reject します。
platform は複数 tenant / issuer / app profile に valid key を持つことがあるため、「何か valid signature がある」だけでは current trust domain の証明になりません。
issuer と audience を混同しない
iss— 誰が発行したか。aud— 誰向けか。
trusted issuer が発行した token でも Orders API ではなく Billing API 向けなら reject されます。
私の validation sequence は:
trusted signature
↓
issuer
↓
audience
↓
exp / nbf
↓
token type + scopes/roles
です。
multi-tenant の issuer
次を確認します。
- tenant ごとに unique issuer か。
- library は tenant-specific issuer を期待するか。
- JWKS key が tenant 間で shared か。
- API が複数 issuer を意図的に allow しているか。
- issuer selection が trusted config から来ているか。
「同じ hostname 以下なら全部許可」のような broad rule は、security model が明示していない限り作りません。
複数 issuer を support するなら allowlist と issuer ごとの metadata / key policy を持ちます。
slash / path / scheme の差を文字単位で見る
configured: https://id.example.com/tenant/
token iss: https://id.example.com/tenant
のような差を確認します。
- trailing slash
- tenant path
httpsvshttp- hostname / environment
- accidental whitespace
- migration 前の old issuer
を見ます。
spec が許可しない normalization を勝手に行いません。
metadata を使えるなら 3 点比較する
configured issuer
metadata issuer
JWT iss
を比較し、metadata の jwks_uri も確認します。
この 3 点が一致しないなら JWT library より discovery / configuration の問題を先に疑います。
私がやらない修正
- issuer validation を無効化する。
- valid signature を作れる issuer を全部 trust する。
- unverified
issだけを見て dynamic JWKS を trust する。 - JWT 内の
issを編集する。 - audience check で issuer check を代用する。
私の issuer-validation checklist
- JWT を decode し
iss/kid/alg/audを読む。 - resource server が期待する exact issuer を特定する。
- dev / staging / prod と tenant の取り違えを見る。
- trusted config から metadata / JWKS を得る。
- trusted JWKS で
kidを選ぶ。 - issuer-owned key で signature verify。
- authenticated
issと expected issuer を exact compare。 aud/exp/nbf/ token profile を続けて validate。- server auth log の issuer error を読む。
- validation を弱めず trust / configuration path を直す。
issuer validation は 見慣れた URL が入っているかではなく、信頼する issuer に属する key で token を authenticate し、signed issuer identifier が expected identity と一致するかを確認する作業です。