JWT(JSON Web Token)は、WebアプリケーションやAPIで認証情報などをやり取りするために使われるトークン形式です。サーバーとクライアントの間で必要な情報をコンパクトに受け渡しできるため、ログイン後のAPIアクセスやセッション管理の設計でよく検討されます。
一方で、JWTは「発行すれば安全になる」仕組みではありません。署名の検証、保存場所、有効期限、失効方法を適切に設計してはじめて、安全性と運用しやすさのバランスが取れます。この記事では、JWTの基本構造から認証フロー、導入時の注意点までを整理します。
JWTとは
JWTは、JSON形式の情報をトークンとして表現し、クライアントとサーバー間でやり取りするための形式です。主に、ログイン済みユーザーを識別する認証トークンや、APIにアクセスするためのトークンとして使われます。
JWTはピリオドで区切られた3つの部分で構成されます。それぞれをBase64URLエンコードして連結することで、1つの文字列として扱えるようになります。
| 構成要素 | 役割 |
|---|---|
| ヘッダー | トークンの種類や署名アルゴリズムを示します。 |
| ペイロード | ユーザーID、発行時刻、有効期限などのクレームを入れます。 |
| 署名 | ヘッダーとペイロードが改ざんされていないか確認するために使います。 |
JWTの構造
ヘッダー
ヘッダーには、トークンのタイプと署名に使うアルゴリズムを記載します。たとえば、HMAC SHA-256を使う場合は次のような形です。
{
"alg": "HS256",
"typ": "JWT"
}
- alg: 署名に使用するアルゴリズム。
- typ: トークンのタイプ。JWTでは通常、JWTと指定します。
ペイロード
ペイロードには、クレームと呼ばれる情報を入れます。ユーザーを識別する値や、トークンの発行時刻などを含めることがあります。
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
- sub: ユーザーIDなど、対象を示す識別子。
- name: ユーザー名などの情報。
- iat: 発行日時を表す値。
ペイロードに入れる情報は、必要最小限にすることが重要です。トークンサイズが大きくなると通信量が増え、扱う情報が多いほど漏えい時の影響も大きくなります。
署名
署名は、ヘッダーとペイロードをもとに生成されます。サーバー側で署名を検証することで、トークンが途中で改ざんされていないか確認できます。
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret
)
署名は改ざん検知のための仕組みです。トークンの保存場所や通信経路まで含めて設計し、トークンそのものを不用意に露出させないことが重要です。
JWTを使った認証フロー
JWTを使う認証では、ログイン後に発行されたトークンをクライアントが保持し、以後のAPIリクエストに添えて送信します。基本的な流れは次の通りです。
- ユーザー認証: ユーザーがログインし、サーバーがユーザー名やパスワードなどの資格情報を確認します。
- JWTの発行: 認証に成功すると、サーバーが署名付きのJWTを発行します。
- クライアントで保持: ブラウザやモバイルアプリが、用途に応じた場所にトークンを保存します。
- APIリクエストに添付: クライアントはリクエスト時にJWTを
Authorizationヘッダーへ含めます。 - サーバーで検証: サーバーは署名、有効期限、必要なクレームを確認します。
- リソースを返却: トークンが有効であれば、要求されたデータや機能を提供します。
リクエストでは、次のようにBearerトークンとして送る形が一般的です。
GET /protected-resource HTTP/1.1
Host: api.example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
JWTの保存場所と有効期限
JWTを安全に使ううえで、クライアント側の保存場所は重要です。保存方法にはそれぞれ利点と注意点があります。
| 保存先 | 特徴 | 注意点 |
|---|---|---|
| ローカルストレージ | 実装しやすく、クライアント側で扱いやすい。 | XSS攻撃で読み取られるリスクがあるため、入力値の無害化や表示処理の対策が欠かせません。 |
| クッキー | Secure属性やHttpOnly属性を使うことで、ブラウザ側の保護を強めやすい。 | 用途に応じて属性設定やリクエスト設計を慎重に決める必要があります。 |
また、JWTには通常、有効期限を設定します。アクセス用のJWTは短めにし、必要に応じてリフレッシュトークンで新しいトークンを発行する設計にすると、盗まれたトークンが長く使われるリスクを下げられます。
JWTのメリット
ステートレスな認証を設計しやすい
JWTを使うと、サーバーがセッション情報を常に保持しなくても、トークンの署名と内容を検証してユーザーを識別できます。複数のサーバーでAPIを運用する場合にも、構成をシンプルにしやすい点があります。
認証以外の情報も扱える
JWTには、認証に必要な情報だけでなく、アクセス権限やリソースに関する制約を含めることもできます。ただし、ペイロードに入れる情報が増えるほどサイズと管理上のリスクも増えるため、必要な情報に絞ることが前提です。
APIやクロスドメイン構成で使いやすい
JWTはHTTPヘッダーに含めて送信しやすいため、Webアプリケーション、モバイルアプリ、APIを組み合わせた構成でも扱いやすい形式です。CORSを含む構成では、認証方式だけでなく、許可するオリジンやヘッダーもあわせて設計します。
セキュリティで確認すべきポイント
JWTは便利ですが、設計や実装を誤ると不正アクセスの原因になります。導入時は、少なくとも次の点を確認します。
- 強い秘密鍵を使う: 署名に使う鍵が弱いと、トークンの改ざんや推測のリスクが高まります。
- HTTPSで通信する: トークンが盗聴されないよう、通信経路を暗号化します。
- 有効期限を短くする: アクセストークンを長期間有効にしすぎると、漏えい時の影響が大きくなります。
- アルゴリズムを明示的に選ぶ: 古い方式や弱い方式を避け、サーバー側で許可するアルゴリズムを明確にします。
- 失効の仕組みを用意する: ログアウト、リフレッシュトークンの失効、不正利用時の無効化を運用に含めます。
- ペイロードを最小限にする: ユーザー識別や認可に必要な情報だけを入れ、不要な個人情報や大きなデータは含めないようにします。
JWTのデメリットと考慮点
トークンサイズが大きくなりやすい
JWTはペイロードに情報を含められるため、便利な反面、情報を詰め込みすぎるとサイズが大きくなります。通信量やレスポンス速度に影響する可能性があるため、必要最小限のクレームに絞ることが大切です。
盗まれたトークンが再利用される可能性がある
有効なJWTを第三者に盗まれると、有効期限が切れるまで不正に使われる可能性があります。短い有効期限、HTTPS、保存場所の設計、失効管理を組み合わせて対策します。
完全な失効管理には工夫が必要
JWTはステートレスに扱いやすい一方で、すべてのトークンをサーバー側で常時管理する方式とは性質が異なります。ログアウトや不正利用時に即時無効化したい場合は、ブラックリストや発行履歴の確認など、追加の管理方法を検討します。
導入前のチェックリスト
- JWTに入れるクレームは必要最小限か。
- アクセストークンとリフレッシュトークンの有効期限は適切か。
- トークンの保存場所とブラウザ側の攻撃対策を決めているか。
- サーバー側で署名、期限、必要なクレームを検証しているか。
- ログアウトや不正利用時の失効手順を用意しているか。
- APIの認可設計とトークンの権限範囲が一致しているか。
関連して読みたい記事
- 基本用語を短く確認したい場合: JWT(JSON Web Token)とは?
- 実装フレームワークでのAPI保護を確認したい場合: FastAPIセキュリティ実践ガイド:JWT認証・OAuth2スコープ・APIキーで守るモダンAPI設計
まとめ
JWTは、WebアプリケーションやAPIでトークンベース認証を実現するための有力な選択肢です。ヘッダー、ペイロード、署名という構造を理解し、保存場所、有効期限、失効方法まで含めて設計することで、扱いやすく安全な認証基盤に近づけられます。
特に重要なのは、強い鍵を使うこと、HTTPSで通信すること、アクセストークンの有効期限を短くすること、不要な情報をペイロードに入れないことです。JWTはシンプルに見えますが、実運用では認証・認可・ログアウト・不正利用時の対応まで一体で考える必要があります。
greedenでは、システム開発やソフトウェア設計に関する相談を受け付けています。JWTを使った認証設計、API連携、セキュリティを考慮したアプリケーション開発でお困りの際は、お問い合わせフォームからお気軽にご相談ください。
