本文へスキップ
App Museum
English

JWTデコーダー

JWT(JSON Web Token)のヘッダーとペイロードをデコードして表示し、有効期限(exp)を現在の時刻と比べます。共有シークレットや公開鍵を入れれば、HS256・RS256・ES256 などの署名が一致するかも、ブラウザの中で確かめられます。

使い方

  1. JWT(header.payload.signature の形式の文字列)を入力欄に貼り付けます。先頭に Bearer が付いたままでもかまいません
  2. ヘッダーとペイロードが、インデント付きのJSONとして表示されます。ボタンを押す必要はありません
  3. ペイロードに exp、iat、nbf があれば、その下に日時へ変換した値が、UTCと端末のタイムゾーンの両方で並びます
  4. その下に、exp と nbf を端末の時計と比べた結果が、「期限切れ」「期限内」「開始前」のいずれかで表示されます
  5. 最後に、署名の部分が元の文字列のまま表示されます
  6. 署名を確かめるときは、その下の「署名を確かめる」の欄に鍵を入れます。alg が HS256 などのトークンは発行者と共有するシークレット、RS256・PS256・ES256 などのトークンは発行者の公開鍵です。入れるとすぐに「署名が一致しました」か「署名が一致しません」が表示されます

鍵を入れなければ、デコードと期限の比較だけを行います。署名が一致しても、確かめたのは「入れた鍵でその署名が作られたこと」だけで、トークンが有効であることやサーバーに受け入れられることは示しません。

具体例

次のJWTを貼り付けます。

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Header:

{
  "alg": "HS256",
  "typ": "JWT"
}

Payload:

{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022
}

時刻の欄には iat として 2018-01-18T01:30:22.000Z が表示され、その下に同じ時刻が端末のタイムゾーンで表示されます。日本時間に設定した端末では、ローカル: 2018/01/18 10:30:22 JST のようになります。このトークンには exp がないため、時刻の欄の下には「数値の exp がないため、期限は比べられません」と表示されます。Signature の欄には、3つ目の部分である SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c がそのまま表示されます。

このトークンの alg は HS256 なので、その下に「共有シークレット(HS256)」の欄が出ます。your-256-bit-secret と入力すると「署名が一致しました」と表示されます。このシークレットは19バイトで、HS256 に必要な32バイトより短いため、短いという注意も出ます。1文字でも違うシークレットを入れると「署名が一致しません」になります。

JWTの構造と表示される内容

このアプリが扱う署名付きのJWT(JWS形式)は、ピリオドで区切られた3つの部分からできています。

  • ヘッダー: 署名のアルゴリズム(alg)やトークンの種類(typ)を記したJSON
  • ペイロード: 利用者の識別子や有効期限などの情報(クレーム)を記したJSON
  • 署名: ヘッダーとペイロードが書き換えられていないことを、鍵を使って確かめるための値

ヘッダーとペイロードは、JSONをBase64URLという形式で表しただけのもので、暗号化はされていません。そのため、鍵がなくても誰でも中身を読めます。このアプリは、その2つを読める形に戻して表示します。Base64URLは + と / の代わりに - と _ を使い、末尾の = を省く形式ですが、貼り付けた文字列を自分で置き換える必要はありません。

ペイロードでよく使われるクレームには、発行者の iss、対象の利用者を表す sub、想定する受信者の aud、有効期限の exp、有効になる時刻の nbf、発行時刻の iat、トークンの識別子の jti があります。

時刻クレームの読み方

exp、iat、nbf は、1970年1月1日0時(UTC)からの経過秒数で書かれます。このアプリは、値が数値のときに限り、2018-01-18T01:30:22.000Z の形式に変換し、その下に同じ時刻を端末のタイムゾーンで表示します。

  • 1行目の末尾の Z はUTC(協定世界時)を表します
  • 2行目の「ローカル」は、このページを開いている端末のタイムゾーンでの日時で、末尾にタイムゾーンの名前が付きます。日本時間はUTCより9時間進んでいるため、上の例は2018年1月18日10時30分22秒です
  • 値は秒として扱います。ミリ秒の値が入っているトークンでは、遠い未来の日付が表示されます
  • "1760003600" のように文字列で書かれた値は変換されず、ペイロードのJSONにだけ表示されます
  • 8,640,000,000,000秒を超える数値は日時として表せないため、変換されず、ペイロードのJSONにだけ表示されます。マイナス側も同じです。下の期限の比較には、この場合も数値のまま使われます
  • 表示の順序は exp、iat、nbf です

秒数と日時を相互に変換したいときは、Unixタイムスタンプ変換ツールが使えます。

期限の比較

時刻の欄の下には、exp と nbf を端末の時計と比べた結果が1行で表示されます。次の順に調べ、最初に当てはまったものが選ばれます。

  1. 現在の時刻が exp と同じか、それより後なら、「期限切れ: exp を 3日 2時間過ぎています」
  2. 現在の時刻が nbf より前なら、「開始前: nbf まであと5分」
  3. 現在の時刻が exp より前なら、「期限内: exp まであと2時間 15分」
  4. 数値の exp がなければ、「数値の exp がないため、期限は比べられません」
  • 長さは、日、時間、分、秒のうち大きいほうから2つの単位で表し、それより小さい単位は切り捨てます。3日2時間59分は「3日 2時間」、1日0時間30分は「1日」、1分未満は「45秒」のようになります
  • iat は比較に使いません
  • 時計を読むのは、入力欄の内容が変わったときです。ページを開いたままにしても表示は進みません。比べ直すには、入力欄の内容を変えてください。いつの時計と比べたかは、結果の下に表示されます
  • 比べる相手は端末の時計です。端末の時計がずれていれば結果もずれます。サーバーが時計のずれをどこまで許すかも、ここには反映されません

「期限内」は、exp に書かれた時刻がまだ来ていないことだけを表します。署名が一致していても、トークンが有効であることや、サーバーに受け入れられることは示しません。

署名の確かめ方

対応している alg は、HS256・HS384・HS512、RS256・RS384・RS512、PS256・PS384・PS512、ES256・ES384・ES512 です。計算はブラウザに組み込まれた Web Crypto で行い、鍵は送信も保存もしません。

HS で始まる alg(共有シークレット)

  • 入力したシークレットを、そのままの文字列(UTF-8)として使います。前後の空白も取り除きません
  • シークレットが Base64 や Base64URL で保存されている場合は、「シークレットは Base64 または Base64URL で書かれている」を選ぶと、元のバイト列に戻してから使います。末尾の = はあってもなくてもかまいません
  • 入力中の文字は伏せて表示されます。確かめたいときは「シークレットを表示する」を選びます
  • シークレットが、HS256 なら32バイト、HS384 なら48バイト、HS512 なら64バイトより短いときは、一致したかどうかと一緒に「推測されるおそれがあります」と表示されます。RFC 7518 は、これより短いシークレットを使わないよう求めています
  • 公開鍵のように見える値は、使わずに理由を表示します。PEM、PEM の外枠を外した中身、DER(SPKI と PKCS#1)、JWK を、入力した文字列と、Base64 として戻したあとのバイト列の両方で調べます。公開鍵は誰でも手に入るため、公開鍵をシークレットとして確かめると、攻撃者が作った偽のトークンでも一致してしまうからです。ただし、どんな書き方の公開鍵でも見分けられるわけではありません。公開鍵をこの欄に入れないでください。秘密鍵の PEM を入れた場合も使いません。"kty":"oct" の JWK の場合は、k の値だけを貼り付け、Base64 の選択肢を選んでください

RS・PS・ES で始まる alg(公開鍵)

  • -----BEGIN PUBLIC KEY----- で始まる PEM か、JWK の JSON を貼り付けます
  • JWKS({"keys":[...]} の形の鍵の一覧)も貼り付けられます。ヘッダーに kid があれば、同じ kid の鍵を1つだけ使い、どの鍵を使ったかを表示します。ヘッダーに kid がないときは、鍵が1つだけの JWKS に限って使えます。ヘッダーの kid が文字列でないときや、keys に鍵でないものが含まれるときは、鍵を選びません
  • JWK の鍵の種類はトークンの alg と合っている必要があります。RS と PS は "kty":"RSA"、ES256 は "crv":"P-256"、ES384 は "crv":"P-384"、ES512 は "crv":"P-521" です。JWK に alg、use、key_ops が書かれていれば、それがこのトークンの署名の確認に使えるものかも確かめます
  • 秘密鍵(-----BEGIN PRIVATE KEY----- など、または d を含む JWK)は使いません。署名を確かめるのに必要なのは公開鍵だけです
  • 証明書(-----BEGIN CERTIFICATE-----)と、-----BEGIN RSA PUBLIC KEY----- の形式(PKCS#1)は読めません。-----BEGIN PUBLIC KEY----- の形式か JWK に変換してから貼り付けてください

確かめないもの

  • alg が none のトークンには署名がないため、確かめられません。EdDSA など、上の一覧にない alg にも対応していません
  • ヘッダーに crit があるトークンは、確かめません。crit は「この拡張を理解できない受け手はトークンを拒否する」という印で、このツールは拡張を扱えないためです
  • 鍵は、入力欄に入れたものだけを使います。ヘッダーの jwk・x5c に書かれた鍵や、jku・x5u が指す URL の鍵は使わず、URL にアクセスすることもありません。トークンを作った人なら、ヘッダーに自分の鍵を書けるからです
  • 3つの部分はどれも、余分な =・空白・+・/ を含まない、正確な Base64URL である必要があります。ヘッダーかペイロードがそうでない場合は鍵の欄を出さず、署名がそうでない場合は一致したかどうかではなく、読めないことを表示します。そのように書かれた JWT は、その形のまま署名されていても正しいトークンではないためです
  • iss・aud などのクレームや期限は、署名と一緒には確かめません。期限は上の比較を見てください

署名は、トークンか鍵が変わるたびに確かめ直します。入力中は、古いトークンや鍵での結果を表示しません。

エラーになる入力

  • ピリオドで区切った部分が3つでない場合は、「JWTは header.payload.signature の3セグメント構成である必要があります」と表示されます。5つの部分からなる暗号化されたトークン(JWE)は扱えません
  • ヘッダーやペイロードの文字が欠けてBase64URLやJSONとして読めなくなった場合は、エラーになります。署名の部分が欠けていても、デコードのエラーにはなりません。鍵を入れたときに、署名が一致しないか、Base64URLとして読めないと表示されます
  • 先頭の Bearer とそれに続く空白は、取り除いてから読みます。大文字と小文字は区別しません。Authorization ヘッダーの値をそのまま貼り付けられます。Authorization: のようなヘッダー名まで含めた場合は、エラーになります
  • ヘッダーまたはペイロードが、有効なUTF-8のJSONに戻らない場合もエラーになります

3つに分かれているのに読み取れない場合は、ブラウザが返したエラーの原文(英語)が表示されます。前後に付いた空白や改行は、自動で取り除かれます。

デコードと署名検証の違い

デコードは中身を読むだけの操作です。ペイロードを書き換えた偽のトークンでも、このアプリでは同じように表示されます。鍵を入れれば、偽のトークンは「署名が一致しません」になります。

ただし、「署名が一致しました」で分かるのは、入れた鍵でその署名が作られたことだけです。その鍵が本当に信頼する発行者のものか、iss・aud・期限がシステムの方針に合うかは確かめていません。トークンを信頼してよいかどうかは、許可するアルゴリズムと鍵を決めて署名を確かめ、exp や aud を検査するサーバー側の処理で決まります。認証や権限の判断には、このアプリの表示を使わないでください。

違いの詳しい説明は、ガイド「JWTのデコードと署名検証の違い」にあります。

FAQ

署名は検証されますか?

鍵を入れたときだけ確かめます。HS で始まる alg のトークンには共有シークレットを、RS・PS・ES で始まる alg のトークンには公開鍵を入れてください。鍵を入れなければ、ヘッダーとペイロードを表示して期限を比べるだけです。

秘密鍵やシークレットを入力する必要がありますか?

デコードと期限の比較だけなら、何も入力する必要はありません。署名を確かめるとき、HS のトークンでは発行者と共有するシークレットが必要です。RS・PS・ES のトークンで必要なのは公開鍵だけで、秘密鍵は不要です。秘密鍵を貼り付けても使いません。

公開鍵はどこで手に入りますか?

多くの発行者は、公開鍵の一覧を JWKS として公開しています。OpenID Connect の発行者なら、発行者の URL の末尾に /.well-known/openid-configuration を付けた文書の、jwks_uri に書かれた URL です。このアプリは URL にアクセスしないため、その URL をブラウザで開き、表示された JSON をそのまま貼り付けてください。

有効期限が切れているかどうかは分かりますか?

exp が数値で入っていれば、端末の時計と比べて「期限切れ」か「期限内」かと、その差が表示されます。exp がまだ先でも、nbf が現在より後なら「開始前」と nbf までの差が表示されます。ただし、「期限内」と表示され、署名が一致しても、トークンが有効だとは限りません。

表示される日時は日本時間ですか?

1行目は末尾に Z が付いたUTCの日時です。その下の「ローカル」の行が、端末のタイムゾーンでの日時です。端末が日本時間に設定されていれば、日本時間で表示されます。

本番環境のトークンを貼り付けても大丈夫ですか?

貼り付けたトークンと鍵は、ブラウザの中で使われるだけで、外部への送信も保存もされません。ただし、有効期限内のトークンはそれ自体が認証情報です。画面の共有中やスクリーンショットに写り込まないように注意してください。

HS のシークレットは、それを知っていれば誰でも正しい署名のトークンを作れる値です。本番のシークレットはできるだけ使わず、検証用の環境のシークレットで試してください。画面の共有中は「シークレットを表示する」を選ばないでください。公開鍵は公開してよい値なので、貼り付けても問題ありません。

JWTのペイロードに秘密の情報を入れてもよいですか?

入れないでください。署名付きのJWTのペイロードは暗号化されておらず、トークンを手にした人なら誰でもこのアプリと同じ方法で読めます。

種別
ユーティリティ
カテゴリ
開発者向け
タグ
jwt
json
token
decoder
expiration
signature
developer
  • JWTのデコードと署名検証の違い

    JWTのheader・payload・signatureを読み解き、内容のデコードだけでは正当性を判断できない理由と安全な確認手順を解説します。

    開発者向けjwtjwsauthenticationsecurity
  • JSON整形ツール

    JSONを見やすく整形・圧縮し、キーの並べ替えや、大きな整数などの数値を入力の書き方のまま残すこともできる無料ツール。構文エラーは行と文字目、原因を示します。ブラウザ内で処理され、データは送信されません。

    ユーティリティ開発者向けjsonformatterdeveloper
  • UUID・ULID生成ツール

    UUID v4 と、時刻順に並ぶ UUID v7・ULID をまとめて生成。ボタンひとつで最大100件を作成し、UUIDは大文字・ハイフンなし・波かっこ付きの形式に切り替えてコピーできます。貼り付けたUUID・ULIDのバージョンと作成時刻を調べ、ULIDとUUIDの書き方を相互に変換することもできます。

    ユーティリティ開発者向けuuidguiduuidv4uuidv7ulidgeneratordecodertimestampdeveloperid
  • JSON⇔YAML変換ツール

    JSONとYAMLを相互に変換します。--- 区切りの複数ドキュメントのYAMLとJSON配列の相互変換にも対応し、設定ファイルの書式変換やデータ確認に使えます。

    ユーティリティ開発者向けjsonyamlconverterdeveloper