本文へスキップ

JWTデコーダー

JWTを貼り付けるとheaderとpayloadをJSONに戻し、exp・iat・nbfを日付と時刻に直して、期限切れかどうかと一緒に表示します。署名は検証しません。

署名は未検証

このツールは内容を読むだけで、署名は検証しません。本番環境のトークンや実際の秘密鍵は、このツールを含め、どんなオンラインツールにも貼り付けないでください。

JWTを貼り付けるとheaderとpayloadが解析されます。

入力した内容はこのブラウザの中だけで処理され、サーバーには送信されません。 仕組みを見る

JWTの3部分とデコードしたペイロード。デコードは署名検証とは異なる

使い方

「JWTを貼り付け」の欄にトークンを入れると、結果は次の5つに分かれて出ます。

  1. 期限の表示:payloadにexpがあるときだけ、いちばん上に「期限内」か「期限切れ」がexpの時刻と一緒に出ます。 この通知はexpと端末の時計だけを比較した結果で、nbfの開始時刻や署名の検証結果を示すものではありません。
  2. Header、Payload:それぞれインデントを付けたJSONで表示します。見出しの横のボタンで片方ずつコピーできます。
  3. 署名アルゴリズム:headerのalgの値です。algがないときや文字列でないときは「表示なし」になります。
  4. Signature(原文のまま、未検証):3つ目の部分を、何も手を加えずにそのまま見せます。
  5. 登録済みクレーム:exp(有効期限)、iat(発行時刻)、nbf(有効開始時刻)を日付と時刻に直します。payloadに入っていない項目は「なし」です。

日付と時刻は、開いているブラウザのタイムゾーンで出ます。サーバーのログがUTCで記録されているなら、時差の分だけ食い違って見えます。

サンプルで確かめる

試しに次のトークンを貼り付けてみてください。

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyLTQyIiwiaWF0IjoxNzY3MjI1NjAwLCJleHAiOjE3NjcyMjkyMDB9.c2lnbmF0dXJl
  • Headerは {"alg": "HS256", "typ": "JWT"} となり、署名アルゴリズムにはHS256と出ます。
  • Payloadは {"sub": "user-42", "iat": 1767225600, "exp": 1767229200} です。
  • iatの1767225600は2026年1月1日 00:00:00(UTC)、expの1767229200はその1時間後にあたる01:00:00(UTC)です。UTC+9のタイムゾーンのブラウザなら、それぞれ9:00:00、10:00:00と表示されます。すでに過ぎた時刻なので、いちばん上の表示は「期限切れ」になります。
  • 3つ目の部分 c2lnbmF0dXJl は本物の署名ではありません。signatureという単語をBase64URLで書いただけです。それでもエラーにならず、何事もなく読めてしまいます。このツールが署名にはいっさい触れていないことが、この例でわかります。

JWTを構成する3つの部分

JWTは、ドット(.)でつないだ3つの部分(header.payload.signature)でできています。headerには署名アルゴリズム(alg)とトークンの種類(typ)、payloadにはユーザーID・権限・有効期限などのクレームが入ります。クレームとは、トークンに書き込まれた名前と値の組のことです。

headerとpayloadは、JSONをBase64URLという書き方に置き換えただけで、暗号化はされていません。トークンを手にした人なら鍵がなくても中身を読めるので、メールアドレスや社内の権限情報を含むトークンをチャットや課題管理ツールにそのまま貼れば、中身ごと人目にさらすことになります。発行者の鍵から作られるのは最後のsignatureだけで、これはheaderとpayloadが発行後に書き換えられていないかを確かめるために使われます。

このツールが確認しないこと

  • 署名:検証するには発行者の秘密鍵(HMAC系)か公開鍵(RSA・ECDSA系)が要りますが、このツールには鍵を入れる欄がありません。中身がきちんと表示されたからといって、本物のトークンだとは言えません。
  • 期限の判定に使う時計:「期限内」「期限切れ」は、お使いの端末の時計と比べて決めています。端末の時計が狂っていれば、判定も狂います。
  • 猶予時間:現在時刻がexpと同じになった瞬間から「期限切れ」、nbfより前なら「使用開始時刻前」と表示します。RFC 7519は、サーバーどうしの時計のずれを考えて、通常は数分以内の猶予を持たせてもよいとしています。このツールは猶予を持たせないので、サーバーがまだ受け付けているトークンが、ここでは期限切れに見えることがあります。
  • それ以外のクレーム:iss(発行者)やaud(対象)などはPayloadにそのまま出るだけで、値が正しいかどうかまでは見ません。

実際にアクセスを通すかどうかを決めるのは、サーバー側の検証です。本番環境のトークンは、有効期間が切れるまでそれ自体が入館証として通用します。画面の警告にあるとおり、オンラインツールには貼り付けないのが無難です。

exp・iat・nbfの値の読み方

RFC 7519は、この3つのクレームを1970年1月1日 00:00:00(UTC)からの経過秒数で書くと定めていて、この形式をNumericDateと呼びます。このツールが日付に直すのは、値が数値のときだけです。

  • "exp": "1767229200" のように引用符で囲まれた文字列は日付として扱わず、「なし」と表示します。PayloadのJSONには値がそのまま見えているので、クレームがあるはずなのに「なし」と出たら、まず引用符を疑ってください。
  • JavaScriptの日付で表せないほど大きい数値も「なし」になります。
  • 状態が付くのはexpとnbfだけで、iatは時刻を表示するだけです。

読み取れないときは

画面に出るエラー よくある原因
JWTはドット(.)で区切られた3つの部分(header.payload.signature)である必要がありますが、N個ありました トークンを途中までしかコピーしていない。なお、暗号化されたトークン(JWE)は部分が5つあり、このツールでは読めません
header(またはpayload)部分をBase64URLとして読み取れませんでした 先頭に「Bearer 」が付いている、途中に改行が入っている、+・/・= を含む通常のBase64になっている
header(またはpayload)部分はデコードできましたが、正しいJSONではありません JWTではない別の値をドットでつないだだけのものを貼り付けている

Base64URLは、Base64の + と / を - と _ に置き換え、末尾の = を省いた書き方です。このツールは、A〜Z、a〜z、0〜9、-、_ 以外の文字が1つでもあると読み取りません。

参考資料

よくある質問

Authorizationヘッダーの値を「Bearer 」ごと貼り付けても読めますか?

読めません。「Bearer eyJ...」のように先頭に余分な文字が付いていると、「header部分をBase64URLとして読み取れませんでした」というエラーになります。eyJで始まるトークン本体だけを貼り付けてください。前後の空白や改行は無視されますが、トークンの途中に改行や空白が紛れ込んでいる場合も同じエラーになります。

expには数値が入っているのに、数万年先の日付になります。なぜですか?

expが秒ではなくミリ秒で書かれているときの症状です。このツールは仕様どおり値を秒として読みます。たとえば1767229200(2026年1月1日)をミリ秒にした1767229200000は57971年の日付になり、状態も「期限内」のままです。トークンを発行する側で、ミリ秒を秒に直してから入れる必要があります。

expのないトークンはどう表示されますか?

結果上部の有効期限の通知は表示されず、exp欄は「なし」になります。nbfがあれば、その欄だけに「使用開始時刻前」または「使用開始時刻に到達」と表示されます。iatは時刻のみです。

headerのalgが「none」になっているトークンを見かけました。危険ですか?

algがnoneのトークンは署名がなく、誰でも好きな内容で作れてしまいます。このツールはそうしたトークンも普通に読み取ったうえで、「署名アルゴリズム」の下に警告を出します。サーバーがこれを受け入れてしまうと認証をすり抜けられるおそれがあるので、検証コードがalg noneをはっきり拒否しているか確認してください。

最終更新日: