JWT ガイド

JWT の署名検証に失敗したときのデバッグ手順

鍵の不一致、algorithm の不整合、kid、key rotation、HMAC secret の encoding、token bytes の変更を、信頼経路に沿って順に切り分けます。

著者: JWTDecoder.tools最終確認 2026-09-13

編集上の表現について:一人称の記述は JWTDecoder.tools の検証済みワークフローを示すもので、発行者・組織著者は JWTDecoder.tools です。

JWT の署名検証失敗を調べるフロー
algorithm、issuer、kid、鍵選択を確認してから検証設定を変更します。

JWT の署名検証に失敗したとき、私は token を編集したり、検証設定を片っ端から変えたりしません。元の compact JWT を保存し、header の alg / kid、payload の iss を読んで、アプリが信頼する鍵の取得元から逆向きに確認します。

期待する HMAC secret / RSA public key があるなら JWT 署名検証 で元の header.payload bytes をそのまま検証します。

署名検証エラーが示すこと

signed JWT/JWS は:

header.payload.signature

で、signature は encoded header + payload に対して作られます。

失敗の主な候補は:

  • HMAC secret が違う
  • RSA public key が違う
  • issuer / tenant が違う
  • key rotation 後も古い鍵を使っている
  • kid で別の鍵を選んでいる
  • 想定外の algorithm
  • token bytes が変更されている
  • key / PEM の形式や encoding が合っていない

です。

Step 1: 元の token を変更しない

payload の role を user から admin に変えるだけでも signed bytes は変わります。

JSON の意味が同じに見えても signature は意味上の object ではなく bytes に対して計算されます。私はデバッグ前に元の compact JWT を保ち、segment を再構成しません。

Step 2: alg / kid / iss を読む

{
  "alg": "RS256",
  "kid": "key-42"
}

これらは手掛かりであって、信頼そのものではありません。

alg は token が使用したと主張する algorithm、kid は signer が選択してほしい鍵 ID、iss は発行者だと主張する値です。

実際に許可する algorithm / issuer / key は application config が決めます。

Step 3: 期待する algorithm を固定する

application が RS256 を期待するなら verifier は RS256 の allowlist を持つべきです。header が HS256 と主張したからといって自動で切り替えません。

RFC 8725 が algorithm を明示的に制限するよう求める理由でもあります。

Step 4: key を issuer まで追う

HS256 なら shared secret の正確な bytes を確認します。

RS256 なら public key が信頼する issuer に属することを確認します。

よくある原因:

  • production token を development key で検証している
  • tenant が違う
  • PEM の header/footer が欠けている
  • certificate と SPKI public key の形式が合っていない
  • JWKS cache が古い
  • 別の JWK を選んでいる

任意の key で signature が通っても意味はありません。application が信頼すると決めた取得元の key で通る必要があります。

Step 5: kid と rotation を見る

kid があるなら、信頼する key set と正確に一致するか確認します。

key が見つからない場合は:

  • JWKS cache が古い
  • issuer が key rotation した
  • environment が違う
  • issuer URL が違う
  • key selection の実装に問題がある

といった原因を疑います。

kid は key selection のための hint であり、identity proof ではありません。詳しくは JWT kid ガイド を使います。

Step 6: HMAC secret の encoding

HS256 では同じ設定文字列に見えても、実際の bytes が違うことがあります。

  • raw UTF-8 か Base64 decode 後の bytes か
  • 余計な whitespace / newline が入っていないか
  • environment ごとに secret が違わないか
  • rotation 前後の secret が混在していないか

を確認します。

弱い password に変えて通すのは修正ではありません。RFC 8725 は弱い HMAC secret に対する offline guessing risk を指摘しています。

Step 7: signature が通っても validation は続く

signature 成功後も:

  • exp / nbf
  • iss
  • aud
  • token type
  • scopes / roles

を確認します。

cryptographic layer が正しいだけで API acceptance は完了しません。JWT Validator と JWT デバッガー を続けて使います。

私がやらない shortcuts

  • signature verification を無効化する
  • token が指定した algorithm をすべて受け入れる
  • token が指定した任意の URL から key を取得して信頼する
  • payload を編集して古い signature が通ると考える
  • decode success を verify success と扱う

私の invalid-signature checklist

  1. 元の compact JWT を保存する。
  2. decode して alg / kid / iss / aud を見る。
  3. application の allowed algorithm を確認する。
  4. trusted issuer と expected key source を確認する。
  5. kid を現在の trusted key set と比較する。
  6. rotation / environment / tenant mismatch を確認する。
  7. HMAC なら secret bytes / encoding を見る。
  8. RSA なら public key format と provenance を見る。
  9. JWT 署名検証 を trusted key で実行する。
  10. signature が通るのに 401 なら issuer / audience / time へ進む。

invalid signature は単なる parse error ではありません。verifier が想定した信頼経路で integrity / authenticity を確立できていないという signal なので、私は bypass せず trust path を修正します。

出典・参考資料

関連ガイド