JWTデコーダー

JSON Web Tokenを貼り付けて、その内容を読んでみましょう。誰が発行したか、誰に向けたものか、何を許可しているか、いつ無効になるか。トークンがこのページの外に出ることはありません。

トークンは入力や貼り付けに合わせてこのページ内でデコードされます。当サイトに送信されず、保存もされず、アドレスにも追加されません。先頭のBearerと改行は無視されます。

本番環境の実際のトークンはパスワードと同じように扱ってください: 有効期限が切れるまでは、持っている人なら誰でもあなたとして操作できます。自分が管理していないWebサイトには貼り付けないでください。

ドットでつながった3つのテキスト

ウェブサイトにログインしたあと、サーバーは次のリクエストでもあなたを見分ける必要があります。よく使われるのが、署名付きの短いメモをブラウザーに渡す方法です。「これはユーザー48213、注文の閲覧が可能、15時15分まで」といった内容です。このメモがJSON Web Token、略してJWTです。

JWTは長いランダムな文字列に見えますが、形はいつも同じ、header.payload.signature です。

  • ヘッダーは小さなJSONオブジェクトで、署名のアルゴリズム(alg)と、多くの場合は使われた鍵(kid)を示します。
  • ペイロードはクレームのJSONオブジェクトです。クレームとは、sub(誰か)、aud(どのサービス向けか)、exp(いつまでか)といった記述のことです。
  • 署名は、最初の2つの部分と鍵から計算した封印です。

ヘッダーとペイロードはBase64URLで書かれています。これはバイト列を英字、数字、-、_ で表す方式で、アドレスやHTTPヘッダーを通っても壊れません。ほぼすべてのトークンが eyJ で始まるのもそのためで、{" をこの方式で表すとそうなります。

エンコードは暗号化ではありません

Base64URLは表記方法にすぎません。何も鍵をかけておらず、テキストに戻すのに鍵は要りません。このページがしているのはそれだけです。つまり、署名付きのJWTは何も隠していません。ペイロードにメールアドレス、ロール、内部IDが入っていれば、トークンを手にした誰でも読めます。ブラウザー拡張機能でも、プロキシのログでも、スクリーンショットでも同じです。

署名がもたらすのは完全性です。ペイロードを1文字でも変えると封印が合わなくなり、サーバーはトークンを拒否します。読むことはできても、書き換えることはできないのです。

5つの部分からなるトークンは別物で、JWEと呼ばれ、中身は本当に暗号化されています。このツールはそのヘッダーを表示し、5つの部分を説明して、そこで止まります。鍵を求めることは決してありません。

このページが読み取るものと指摘するもの

デコーダーは先頭の Bearer、空白、改行を取り除き、トークンを分割して、ヘッダーとペイロードを整形したJSONで表示します。そのあとクレームを一つずつ確認します。3つの日時、exp、nbf(この時刻より前は無効)、iat(発行時刻)は、1970年1月1日からの秒数です。お使いのタイムゾーンとUTCで表示し、「あと12分有効」のような残り時間も示します。

検出内容なぜ問題か
期限切れ、またはまだ有効でないお使いの端末の時計と比べています。正しく作られたサーバーはトークンを拒否します。
exp クレームがないサーバーが失効トークンの一覧を持っていない限り、トークンは永久に使えます。
有効期間が30日を超える盗まれたトークンが、その間ずっと使えてしまいます。
alg が noneトークンに署名がありません。誰でも作れます。
日時がミリ秒単位値が1,000倍大きいと、厳密な受け手にとってはトークンが永久に期限切れになりません。
個人データ、または秘密情報のような名前の項目トークンを持つ誰もが読めます。
ヘッダーに jku、x5u、jwkトークンが自分自身の鍵を指しています。偽造者も同じことができます。

アルゴリズムについての説明も表示します。HS256 は一つの共有シークレットで署名と検証の両方を行います。RS256、ES256、EdDSA は鍵ペアを使い、秘密鍵で署名し、公開鍵で検証します。そのため、検証だけを行うサービスはトークンを作れません。

デコードではわからないこと

このページは署名を検証しません。検証には発行者のシークレットか公開鍵が必要です。署名用のシークレットを求めてくるページは、閉じるべきページです。その結果、ここでは偽造トークンも本物も同じように見えます。表示内容は「トークンがこう主張している」と読み、「このトークンは有効だ」とは決して読まないでください。

同じ理由で、「期限切れでない」とは、exp がお使いの端末の時計より後だという意味でしかありません。サーバーは1時間前にトークンを失効させているかもしれません。

受け取る側を実装しているなら、肝心のチェックはあなたのコードで行われます。想定したアルゴリズムだけを受け入れ、すでに信頼している鍵で署名を検証し、そのあと iss、aud、exp を想定値と比べてください。保守されているライブラリを使い、トークンが要求する alg によって処理を分岐させてはいけません。

有効なトークンは認証情報です

期限が切れるまで、Bearerトークンは提示した人なら誰にでも使えます。本番のトークンをウェブサイトに貼り付ければ、そのサイトに渡したことになります。デコードがブラウザー内で行われる場合は別で、ここではそうなっています。トークンを運ぶリクエストはなく、アドレスバーにも書かれず、ブラウザーのストレージにも保存されません。私たちの言葉を信じる必要はありません。開発者ツールのネットワークタブを見るか、ページを読み込んでからオフラインにして貼り付けてみてください。

それでも一番安全なのは、テスト用アカウントのトークンか、期限切れのトークンでデバッグする習慣です。本物のトークンがチャット、チケット、公開ログに出てしまったら、すべての場所からログアウトするか、発行者に失効を依頼してください。

よくある質問

オンラインのデコーダーにJWTを貼り付けても安全ですか?

デコーダーがブラウザー内で動き、何も送信しない場合に限ります。このデコーダーはトークンをローカルで分割・デコードし、トークンを含むリクエストを一切行わず、何も保存しません。本番のトークンについては、それでも期限切れのものかテスト用アカウントのものを使うほうが賢明です。

シークレットキーなしでJWTをデコードできますか?

できます。ヘッダーとペイロードはBase64URLのテキストで、誰でもJSONに戻せます。シークレットや鍵が必要なのは、署名を検証するときと、サーバーが受け入れるトークンを作るときだけです。

JWTのexp、iat、nbfは何を意味しますか?

exp はトークンが受け入れられなくなる時刻、iat は発行された時刻、nbf は受け入れられ始める時刻です。3つとも1970年1月1日(UTC)からの秒数で、ミリ秒ではありません。

トークンがeyJで始まるのはなぜですか?

ヘッダーはJSONオブジェクトなので {" で始まり、この文字はBase64では必ず eyJ になります。ペイロードも同じ理由で同じように始まります。

HS256とRS256の違いは何ですか?

HS256 は一つの共有シークレットで署名と検証を行うため、トークンを検証できるサービスはどれもトークンを偽造できてしまいます。RS256 は秘密鍵で署名し、公開鍵で検証します。そのため、多くのサービスがトークンを検証でき、作れるのは発行者だけになります。

alg noneのトークンはなぜ危険なのですか?

署名がないので、誰でも中身を書き換えられます。それを受け入れるサーバーでは、ユーザーIDやロールを自由に選べてしまいます。受け手は受け入れるアルゴリズムを列挙し、それ以外をすべて拒否する必要があります。