JWT ガイド

JWT の alg none を見つけたときに安全に判断する方法

JWT の alg none が何を意味するか、なぜ署名による integrity がないのか、token header ではなく application 側の algorithm allowlist で判断する方法を解説します。

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

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

alg=none ∉ application allowlist
token alg → application allowlist → accept / reject

JWT を decode して header に:

{ "alg": "none" }

が見えたら、私は通常の signed token として扱うのを止めます。alg: none は 署名なし JWS を意味し、header と payload を保護する signature / MAC がありません。

この形式がすべての文脈で禁止されるわけではありません。しかし、token 自身に「私は署名なしで受け入れてよい」とセキュリティ方針を決めさせることはありません。

最初に確認するのは:

この token type / protocol で署名なし JWT を許可することを application が明示的に決めているか?

です。答えが no なら拒否します。

alg: none が実際に意味すること

RFC 7518 は none を署名なし JWS の algorithm と定義しています。compact representation は:

header.payload.

のように 3 セグメントですが、最後の signature は空です。

JWT デコーダー で header / payload を読むことはできます。しかし、そこに署名検証の対象はありません。

token header をセキュリティ方針にしない

危険な考え方は:

if (header.alg === "none") {
  acceptWithoutSignature();
}

です。

alg は未検証 token の header にある値です。authentication 前の入力に「署名検証が必要か」を決めさせてはいけません。

私は application config に:

const allowedAlgorithms = ["RS256"];

のような allowlist を持たせ、受け取った alg がその集合に含まれるかを確認します。

RFC 8725 も application が許可する algorithms を明示し、それ以外を自動で cryptographic processing に使わないよう求めています。

過去の脆弱性をどう理解するか

典型的な alg: none 問題は「JWT standard が署名なし token を常に信頼せよ」と要求したことではありません。

問題は一部 implementation が token-provided algorithm を緩く扱い、none を自動的に有効な verification mode のように受け入れたことです。

signed token の header を none に書き換え、signature を消した token を壊れた verifier が accept する可能性がありました。

そのため私は decoder に「悪意ある token 判定」をさせるより、verifier の明示的な allowlist を重視します。

decode と verify を分ける

alg: none の payload も普通に読めます。

{
  "sub": "user_123",
  "role": "admin",
  "exp": 1789203600
}

しかし signature / MAC がないなら、誰でもこれらの claim value を作れます。

私は次の流れを使いません。

payload を読めた
→ claims が自然に見える
→ authenticated user と判断

authentication が必要なら、application が定めた cryptographic protection と validation rules を要求します。

none を許せる特殊な文脈

RFC 7518 / RFC 8725 は署名なし JWT の存在自体を否定していません。別 mechanism で cryptographic protection が提供されるなど、integrity が別で保証される文脈では成立します。

ただし重要なのは 明示的に要求されていることです。

私は application 全体に:

allowUnsignedJwt = true

のような広すぎる switch を作りません。必要なら対象 token type を隔離し、通常の signed JWT validation とは別の policy にします。

「すべての algorithm を support」しない

IdP が RS256 を使うなら、例えば:

Allowed: RS256
Rejected: HS256, none, ES256, others

とします。deployment が追加 algorithm を意図的に support する場合だけ allowlist を増やします。

JWT 署名検証 と JWKS Validator も unknown alg を実行命令として扱わず、対応する既知の algorithm / key compatibility を確認します。

invalid signature と alg none は別の状態

Invalid signature は:

signature は存在するが verification が失敗した

alg none は:

signature algorithm がなく、signature segment も空

です。

production token が突然 RS256 から none に変わったなら、public key を変えて試すのではなく token source と verifier policy を調べます。

alg だけで acceptance を決めない

強い allowed algorithm を使っていても、次の checks は必要です。

  • signature verification
  • trusted issuer
  • audience
  • exp / nbf
  • token type
  • scope / role

alg none は分かりやすい extreme case ですが、JWT validation は algorithm だけでは完了しません。

server verifier で欲しい設定

library API は違っても概念は:

verifyJwt(token, trustedKey, {
  algorithms: ["RS256"],
  issuer: "https://login.example.com/",
  audience: "api://orders"
});

です。allowed algorithm は token ではなく、信頼する application config から来ます。

production で alg: none を見たときの checklist

  1. header が本当に "alg":"none" か確認する。
  2. 署名なし JWS として signature segment が空か確認する。
  3. どの service が token を生成したか特定する。
  4. 信頼する config から期待する algorithm を確認する。
  5. verifier に algorithm allowlist があるか確認する。
  6. その token type で none が明示許可されていなければ reject する。
  7. token-type confusion や fallback verification path がないか確認する。
  8. logs で同様の unexpected algorithm change を探す。

私は header を none から RS256 に編集して直そうとはしません。header を変えても valid signature は復元されません。

私のルールは 署名なし JWT を許可するか決めるのは application であり、token 自身ではない という一点です。

出典・参考資料

関連ガイド