JWTデコーダー
JWTのヘッダー・ペイロードを即デコード、有効期限も確認
🔒 入力したトークンはサーバーに送信されず、ブラウザ内でのみ処理されます。
ヘッダー
ペイロード
署名(検証なし)
トークンを入力するとここに結果が表示されます。
処理中…
0.0
停止していません。計算が終わると結果が表示されます。
JWTデコーダーについて
JWT(JSON Web Token、RFC 7519)は、ヘッダー・ペイロード・署名の3つをドットでつないだ文字列です。前の2つはJSONをbase64urlでエンコードしたもので、このツールはそれをデコードしてJSONとして表示し、exp・iat・nbfを日時に直します。
このツールは署名を検証しません。HS256なら共有秘密鍵、RS256やES256なら発行者の公開鍵が必要ですが、デコーダーはどちらも受け取らないからです。ペイロードがきれいに表示されたことは「形式が正しい」ことを示すだけで、「信頼してよい」ことは示しません。
ペイロードは暗号化されていない
base64urlは暗号ではなく表記の変換です。ログやブラウザのlocalStorageからトークンを手に入れた人は、誰でも中身を読めます。署名付きJWT(JWS)のペイロードにパスワードやマイナンバー、社内の権限ルールを入れてはいけません。中身を隠したいならJWE(暗号化JWT)を使います。JWEはドットで区切られた部分が5つあるため、このツールでは「セグメント数エラー」になります。
署名が保証するのは改ざんされていないことです。roleをuserからadminに書き換えて再エンコードすれば、デコーダーにはadminと表示されますが、正しく実装されたサーバーは署名不一致で拒否します。
algヘッダーを信じたときに起きる攻撃
ヘッダーのalgは攻撃者が自由に書き換えられる値です。RFC 8725(JWTのベストプラクティス)は、これを信用したことで起きた代表的な問題を挙げています。
- alg: none:RFC 7519の6章は署名が空文字列の「保護されていないJWT」を定義しています。一部のライブラリはnoneを見て検証を省きました。下の例のように最後のドットの後ろが空のトークンがこれです。
- RS256とHS256の取り違え:サーバーがRSAの公開鍵で検証する設定のとき、攻撃者がalgをHS256に変え、公開鍵をHMACの秘密鍵として署名すると、ヘッダーに従う実装はその偽造を受け入れてしまいます。
- 対策は、検証側のコードで許可するアルゴリズムを固定することです。RFC 8725は、呼び出し側が許可リストを指定できなければならず、それ以外のアルゴリズムを使ってはならないとしています。
- HS256の鍵が短い、または覚えやすい文字列だと、トークン1つからオフラインの総当たりで鍵を割り出されます(RFC 8725 2.2節)。
exp・nbf・iatと時計のずれ
3つとも1970-01-01 UTCからの「秒」です。JavaScriptのDate.now()はミリ秒なので、自作トークンで1000倍の扱いを間違えると、有効期限が数万年先や1970年になります。表示された日時が極端なら、まずこれを疑ってください。
RFC 7519では、exp以降は受け入れてはならず、nbfより前も受け入れてはなりません。どちらにも時計のずれに備えて「通常は数分以内の小さな猶予(leeway)」を設けてよいと書かれています。発行サーバーの時計が30秒進んでいると、受け取ったばかりのトークンがnbfで拒否されることがあります。
このツールの「期限切れ」と「まだ有効ではない」(nbfより前)の表示は、あなたのPCの時計とexp・nbfを比べた結果です。「時計のずれの許容(秒)」に値を入れるとその分の猶予を持たせて判定します(初期値0秒)。iatが未来ならば時計のずれを警告します。iatは発行時刻にすぎず、expがないトークンは規格上期限がありません。
例
jwt.ioのサンプルトークン
- 入力
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c- 結果
ヘッダー {"alg":"HS256","typ":"JWT"} ペイロード {"sub":"1234567890","name":"John Doe","iat":1516239022} 発行 2018-01-18 01:30:22 UTC、有効期限なし
expがないので期限切れの判定は出ません。署名部分は表示されるだけで、正しいかどうかはわかりません。
alg: noneのトークン
- 入力
eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzdWIiOiJhZG1pbiIsImV4cCI6MTc5MDAwMDAwMH0.- 結果
ヘッダー {"alg":"none","typ":"JWT"} ペイロード {"sub":"admin","exp":1790000000} 署名:空、有効期限 2026-09-21 14:13:20 UTC
問題なくデコードできます。本番APIがこの形を受け入れるなら、誰でもsubにadminと書いてログインできることになります。
使い方
- 「Bearer 」を除いたトークン本体を貼り付けます。
- ヘッダーのalg・typとペイロードのクレームを確認します。
- exp・iat・nbfの日時を見ます。期限切れ・nbfの判定はPCの時計と、入力した許容秒数が基準です。
よくある質問
本番のトークンを貼っても大丈夫ですか?
デコードはブラウザ内で完結し、送信はしません。ただし有効なアクセストークンはそれ自体がログイン手段なので、チャットやチケットに貼るのは避けてください。
署名が正しいか確認できますか?
できません。検証はサーバー側のライブラリで、許可するアルゴリズムを明示して行います。
期限切れと出るのにAPIは受け付けます。
サーバーが猶予を設けているか、PCの時計が進んでいる可能性があります。サーバーと同じ猶予を「時計のずれの許容(秒)」に入れると同じ基準で判定できます。
セグメント数エラーになります。
JWTのドットはちょうど2つです。「Bearer 」や引用符が残っていないか、JWE(ドット4つ)でないか確認してください。
出典
基準日: