JWTのデコードと署名検証の違い
JWTのheader・payload・signatureを読み解き、内容のデコードだけでは正当性を判断できない理由と安全な確認手順を解説します。
公開日: 2026-08-10 · 更新日: 2026-08-10
JWTの3つの部分
署名付きJWTでよく使われるJWS Compact Serializationは、ピリオドで区切られた三つの部分から成ります。
base64url(header).base64url(payload).base64url(signature)
headerは、トークンの種類や署名アルゴリズムなどの情報を持ちます。payloadは、sub、aud、expなどのclaimを持つJSONです。signatureは、先頭二部分が改変されていないかを適切な鍵で確認するための値です。
headerとpayloadは通常、暗号化ではなくbase64urlで表現されています。文字列を元のJSONへ戻すだけなら秘密鍵は不要です。この手軽な処理が「デコード」です。
デコードできても正しいとは限らない
攻撃者でもheaderとpayloadを作り、見た目が整った三部分の文字列を組み立てられます。デコード結果に "role":"admin" と書かれていても、署名を検証していなければ発行者がその内容を保証したとは判断できません。
署名検証では、少なくとも信頼する発行者、許可するアルゴリズム、対応する検証鍵を決め、署名が入力と一致するかを確認します。認証や認可の判断では、それに加えて iss、aud、有効期間など、システムのポリシーに必要なclaimを検証します。署名が正しいことだけで、あらゆる用途に受け入れてよいとは限りません。
App MuseumのJWTデコーダーは、headerとpayloadの内容確認用です。署名検証を行わず、トークンが本物か、有効か、認証や認可に使えるかを判断しません。
payloadを信頼してはいけない場面
次の判断を、未検証のデコード結果だけで行わないでください。
- ログイン済みユーザーかどうか
- 管理者権限やアクセス可能な組織
- 課金状態、本人確認状態、利用期限
- 発行者や対象サービスが期待どおりか
UI上の調査でclaimを読むことはできますが、サーバー側のアクセス制御の代わりにはなりません。検証ライブラリを使う場合も、headerの alg を無条件に信頼せず、アプリ側で許可するアルゴリズムと鍵を設定します。
expとiatを時刻として読む
RFC 7519のNumericDateは、1970-01-01 00:00:00 UTCからの秒数です。JavaScriptの Date はミリ秒を受け取るため、表示時には1000倍します。
const payload = {
sub: "example-user",
iat: 1700000000,
exp: 1700003600,
};
new Date(payload.iat * 1000).toISOString();
// expected: "2023-11-14T22:13:20.000Z"
new Date(payload.exp * 1000).toISOString();
// expected: "2023-11-14T23:13:20.000Z"
iat は発行時刻、exp はその時刻以降は受け入れない期限を表します。ただし、claimは省略可能で、未検証の値は改変されている可能性があります。現在時刻との比較には時計ずれの方針も必要です。表示タイムゾーンが異なっても、同じ瞬間を指している点は変わりません。
安全に内容を確認する手順
- 可能なら、実際の認証情報ではなく文書化されたサンプルトークンを使います。
- 実トークンが必要な場合は、共有画面、チャット、Issue、ログへ貼り付けないでください。JWTには個人情報や権限情報が含まれることがあります。
- JWTデコーダーでheaderとpayloadを読み、構造とclaim名を確認します。
expやiatは秒単位としてUNIXタイムスタンプ変換アプリで確認します。- 正当性の判断は、対象システムの信頼設定を持つサーバー側の検証処理で行います。
- 調査後は、コピー、スクリーンショット、履歴、ログにトークンが残っていないか確認します。
デコードは「何と書かれているか」を読む作業、検証は「信頼する発行者がその内容を保護したか」を確かめる作業です。この二つを分けることが安全な調査の出発点です。
参考資料
このガイドで使えるアプリ
- Unixタイムスタンプと日時を相互変換。秒・ミリ秒に対応し、UTCとローカル時刻の両方を表示します。
関連ガイド
- 桁数、値の出所、変換結果を組み合わせ、UNIXタイムスタンプの秒・ミリ秒を安全に判定する手順を解説します。変換unix-timestampsecondsmillisecondsjavascript
- 文字列をUTF-8のバイト列へ変換してからBase64化し、日本語や絵文字の文字化けを避ける手順を解説します。開発者向けbase64unicodeutf-8encoding