JWTとは?構造・デコード方法・セキュリティ注意点
JWT(JSON Web Token)は、WebアプリケーションやAPIの認証・認可に広く使われるトークン形式です。ログイン状態の維持、マイクロサービス間の認証、OAuth 2.0・OpenID Connectの実装など、現代のWeb開発において欠かせない技術となっています。この記事では、JWTの構造と3つの構成要素、デコードの方法、そしてセキュリティ上の注意点を詳しく解説します。
JWTとは?
JWT(JSON Web Token、読み方は「ジョット」)は、RFC 7519で定義されたオープンスタンダードです。当事者間で情報を安全にJSON形式で伝達するためのコンパクトかつ自己完結型の方法を定義しています。
JWTの最大の特徴は、トークン自体にユーザー情報や権限などのクレーム(主張)が含まれている点です。サーバー側でセッション情報を保持する必要がないため、スケーラブルなシステムに適しています。
JWTは以下のようなドット(.)区切りの3つの部分から構成されます:
xxxxx.yyyyy.zzzzz ^ ^ ^ | | | Header Payload Signature
実際のJWTトークンは以下のような長い文字列になります:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
JWTの3つの構成要素
1. Header(ヘッダー)
ヘッダーはトークンのメタ情報を含むJSONオブジェクトです。通常、使用している署名アルゴリズムとトークンタイプの2つのフィールドが含まれます。
{
"alg": "HS256", // 署名アルゴリズム(HMAC SHA-256)
"typ": "JWT" // トークンタイプ
}このJSONをBase64URLエンコードしたものがJWTの第1部分(xxxxx)になります。代表的なアルゴリズムには HS256(HMAC-SHA256)、RS256(RSA-SHA256)、ES256(ECDSA-SHA256)などがあります。
2. Payload(ペイロード)
ペイロードはクレーム(主張)と呼ばれる実際のデータを含むJSONオブジェクトです。クレームには3種類あります:
- Registered claims(登録済みクレーム):RFC 7519で定義された予約済みフィールド(iss, sub, aud, exp, nbf, iat, jti)
- Public claims(パブリッククレーム):IANA JWTクレームレジストリに登録されたフィールド
- Private claims(プライベートクレーム):独自に定義したカスタムフィールド
{
"sub": "1234567890", // Subject(ユーザーID)
"name": "Yamada Taro", // カスタムクレーム
"email": "[email protected]",// カスタムクレーム
"role": "admin", // カスタムクレーム(権限)
"iat": 1516239022, // Issued At(発行時刻:Unixタイムスタンプ)
"exp": 1516242622 // Expiration(有効期限:Unixタイムスタンプ)
}重要:JWTは暗号化ではなくエンコード
ペイロードはBase64URLエンコードされているだけで、暗号化はされていません。誰でもデコードして内容を読むことができます。パスワードや機密情報はペイロードに含めないようにしてください。
3. Signature(署名)
署名はトークンの改ざんを検知するためのものです。エンコードされたヘッダーとペイロードを秘密鍵(または非公開鍵)でハッシュ化して生成します。
// HMAC SHA-256の場合 HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secretKey )
署名は「このトークンが信頼できる発行者から来たこと」と「内容が改ざんされていないこと」を検証するために使われます。ただし、内容の秘密性は保証しません。
Base64URLエンコードの仕組み
JWTではBase64ではなくBase64URLエンコードが使われています。通常のBase64では +、/、= という文字が使われますが、これらはURLの中で特別な意味を持つため、JWTではURLセーフな文字に置き換えられています。
| Base64 | Base64URL | 理由 |
|---|---|---|
| + | - | URLでは + はスペースを意味する |
| / | _ | URLではパスの区切り文字 |
| =(パディング) | 省略 | URLでは = はクエリパラメータの区切り |
JWTデコーダーの使い方
JWTデコーダーを使うと、トークンの各部分(Header・Payload・Signature)を視覚的に確認できます。デバッグ時やトークンの内容を確認したいときに便利です。
- JWTトークン全体(
eyJ...で始まる文字列)をテキストエリアに貼り付けます - 「デコード」ボタンをクリックします
- Header・Payload・Signatureの各パーツが分解・表示されます
- Payloadに含まれるユーザー情報や有効期限(exp)などを確認できます
活用シーン
- • APIレスポンスとして受け取ったJWTの内容確認
- • トークンの有効期限(exp)が切れていないか確認
- • 認証エラーのデバッグ(クレームの中身を確認)
- • 開発中のJWT生成ロジックのテスト
JWTのセキュリティ注意点
1. アルゴリズムの「none」攻撃
JWTのヘッダーで alg: "none" を指定すると、署名なしのトークンを作成できる仕様があります。古い実装ではこれを悪用されるケースがありました。JWTライブラリでは必ず使用するアルゴリズムを明示的に指定し、none を受け入れないよう設定してください。
2. HS256 vs RS256の選択
HS256(対称鍵)は同じ秘密鍵で署名・検証します。単一サービスには適していますが、鍵を複数サービスで共有するとリスクが高まります。RS256(非対称鍵)は秘密鍵で署名し、公開鍵で検証するため、マイクロサービス環境に適しています。
3. 有効期限(exp)を必ず設定する
JWTは一度発行するとサーバー側で無効化しにくいため、有効期限を短く設定することが重要です。アクセストークンは15分〜1時間程度、リフレッシュトークンは7〜30日程度が一般的です。
4. 機密情報はペイロードに含めない
繰り返しになりますが、JWTのペイロードは誰でも読めます。パスワード、クレジットカード番号、個人の機密情報はJWTのペイロードに含めないでください。
5. 保存場所に注意する
ブラウザでJWTを保存する場所によってリスクが異なります:
| 保存場所 | XSSリスク | CSRFリスク | 推奨度 |
|---|---|---|---|
| localStorage | 高い | 低い | △(避けるべき) |
| sessionStorage | 高い | 低い | △(セッション限定) |
| HttpOnly Cookie | 低い | 中(CSRF対策要) | ○(推奨) |
よくある質問
Q. JWTとセッションIDの違いは何ですか?
A. セッションIDはサーバー側でセッション情報を管理し、クライアントはIDのみを保持します。JWTはトークン自体に情報が含まれるためサーバーはステートレスに動作できます。JWTはスケーラビリティに優れますが、無効化(ログアウト)の実装が複雑になります。
Q. JWTの署名を検証しないとどうなりますか?
A. 攻撃者がペイロードを改ざんしたトークンを使用できてしまいます。例えば "role": "user" を "role": "admin" に書き換えた偽トークンを受け入れてしまいます。必ずサーバー側で署名を検証してください。
Q. JWTをデコードしたらペイロードが読めてしまいます。安全ですか?
A. JWTはデフォルトでは暗号化されておらず、誰でもデコードできます。内容を秘密にしたい場合はJWE(JSON Web Encryption)を使用します。通常のJWTは改ざん検知には使えますが、機密性の保護には使えません。
Q. 入力したJWTはサーバーに送信されますか?
A. いいえ。このデコーダーはブラウザ内でのみ処理を行い、入力されたトークンはサーバーに送信されません。ただし実際の本番トークンをオンラインツールに貼り付けることはセキュリティ上推奨されません。開発・テスト用のトークンのみをお使いください。
Q. JWTのexpフィールドを確認するにはどうすればよいですか?
A. expフィールドはUnixタイムスタンプ(1970年1月1日からの秒数)で表されています。JWTデコーダーでデコードするとexp値が表示されますので、現在時刻と比較してトークンが有効かどうか確認できます。
まとめ
JWTはHeader・Payload・Signatureの3つの部分がドットで連結された構造を持つトークン形式です。ペイロードにはユーザー情報や権限などのクレームが含まれ、Base64URLエンコードされているだけで誰でも読めることを理解しておくことが重要です。署名によって改ざんは検知できますが、機密情報は含めないよう注意してください。