JWTデコーダー

JWTのヘッダー・ペイロードを即デコード、有効期限も確認

🔒 入力したトークンはサーバーに送信されず、ブラウザ内でのみ処理されます。

exp・nbf・iatの判定はこの端末の時計が基準です。サーバーと時計がずれている場合は許容秒数を増やしてください。

トークンを入力するとここに結果が表示されます。

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と書いてログインできることになります。

使い方

  1. 「Bearer 」を除いたトークン本体を貼り付けます。
  2. ヘッダーのalg・typとペイロードのクレームを確認します。
  3. exp・iat・nbfの日時を見ます。期限切れ・nbfの判定はPCの時計と、入力した許容秒数が基準です。

よくある質問

本番のトークンを貼っても大丈夫ですか?

デコードはブラウザ内で完結し、送信はしません。ただし有効なアクセストークンはそれ自体がログイン手段なので、チャットやチケットに貼るのは避けてください。

署名が正しいか確認できますか?

できません。検証はサーバー側のライブラリで、許可するアルゴリズムを明示して行います。

期限切れと出るのにAPIは受け付けます。

サーバーが猶予を設けているか、PCの時計が進んでいる可能性があります。サーバーと同じ猶予を「時計のずれの許容(秒)」に入れると同じ基準で判定できます。

セグメント数エラーになります。

JWTのドットはちょうど2つです。「Bearer 」や引用符が残っていないか、JWE(ドット4つ)でないか確認してください。

出典

基準日:

プライバシーとデータの扱い