WebサービスやAPIの認証で「JWT認証」という言葉を目にすることがあります。
JWTは「JSON Web Token」の略で、ユーザーやシステムに関する情報をJSON形式の「Claim(クレーム)」として扱うための、コンパクトなトークン形式です。
JWTを利用すると、ログイン後に発行されたトークンをクライアントからサーバーへ送信し、サーバー側でそのトークンを検証してAPIへのアクセスを許可するといった仕組みを構築できます。
この記事では、JWT認証の基本的な仕組みからJWTの構造、セッション認証との違い、メリット、注意点までわかりやすく解説します。
JWTとは
JWT(JSON Web Token)は、当事者間でClaimをやり取りするためのコンパクトな形式です。
JWTの仕様はRFC 7519として標準化されています。
JWT自体は「認証方式」そのものではなく、情報をやり取りするためのトークン形式です。そのため「JWT認証」という言葉は一般的に、ユーザーの認証後にJWTを発行し、そのJWTを利用して後続のリクエストを処理する仕組みを指して使われています。
JWTはOAuth 2.0やOpenID Connectなどと組み合わせて使用されることもあります。
JWT認証の基本的な仕組み
JWTを利用した一般的な認証フローは、次のようになります。
- ユーザーがIDやパスワードなどを使ってログインする
- サーバーがユーザーの認証情報を確認する
- 認証に成功するとサーバーがJWTを発行する
- クライアントが発行されたJWTを保持する
- APIへのアクセス時にJWTをサーバーへ送信する
- サーバーがJWTの署名や有効期限などを検証する
- JWTが有効であればリクエストを処理する
APIでは、HTTPのAuthorizationヘッダーを利用してトークンを送信する構成があります。
たとえばBearerスキームを使用する場合は、概念的には次のようになります。
Authorization: Bearer <token>
サーバーは受け取ったトークンを検証し、正当なトークンであることを確認したうえでAPIへのアクセスを処理します。
JWTの構造
JWSのCompact Serializationを使った署名付きJWTは、一般的に次の3つの部分から構成されます。
Header.Payload.Signature
それぞれはピリオド「.」で区切られます。
Header
Headerには、署名などに使用するアルゴリズムやトークンの種類に関する情報を含められます。
たとえば次のようなJSONです。
{
"alg": "HS256",
"typ": "JWT"
}
algは署名などに使用するアルゴリズムを示します。
Payload
PayloadにはClaimと呼ばれる情報が格納されます。
たとえば次のような情報です。
{
"sub": "1234567890",
"name": "Taro Yamada",
"iat": 1760000000,
"exp": 1760003600
}
JWTでは、用途に応じてさまざまなClaimを使用できます。
代表的な登録済みClaimには次のようなものがあります。
| Claim | 意味 |
|---|---|
| iss | Issuer。JWTの発行者 |
| sub | Subject。JWTの対象となる主体 |
| aud | Audience。JWTの利用対象 |
| exp | Expiration Time。有効期限 |
| nbf | Not Before。この時刻より前は利用できない |
| iat | Issued At。JWTが発行された時刻 |
| jti | JWT ID。JWTを識別するためのID |
実際にどのClaimを使用するかはシステムの設計によって異なります。
Signature
署名付きJWTでは、SignatureによってJWTが発行後に改ざんされていないことなどを検証できます。
サーバー側では受信したJWTの署名を検証し、検証に失敗したトークンを拒否します。
JWTのPayloadは暗号化されているとは限らない
JWTを扱ううえで特に重要なのが、「JWTに含まれている情報は必ずしも暗号化されているわけではない」という点です。
一般的なJWS形式のJWTでは、HeaderとPayloadはBase64URLエンコードされています。
Base64URLエンコードは暗号化ではありません。そのため、JWTを取得した人はPayloadの内容を読み取ることができます。
したがって、パスワードや秘密鍵など、第三者に知られてはいけない情報を安易にJWTのPayloadへ格納してはいけません。
情報そのものの秘匿性が必要な場合には、JWE(JSON Web Encryption)など、暗号化を行う仕組みを検討する必要があります。
JWTとJWS・JWEの関係
JWTについて理解するときは、JWSとJWEとの違いも重要です。
JWSは「JSON Web Signature」の略で、JSONなどのデータに対してデジタル署名またはMACによる完全性保護を行うための仕様です。
JWEは「JSON Web Encryption」の略で、データを暗号化するための仕様です。
整理すると、概念的には次のように考えられます。
| 用語 | 主な役割 |
|---|---|
| JWT | Claimを扱うトークン形式 |
| JWS | 署名・MACによる完全性や真正性の保護 |
| JWE | データの暗号化 |
JWTだからといって、自動的にPayloadの内容が暗号化されるわけではありません。
JWT認証とセッション認証の違い
Webアプリケーションの認証では、JWTを利用する方法だけでなく、従来からセッションを利用する方法も広く使われています。
典型的なセッション認証では、ログイン後にサーバー側でセッション情報を管理し、ブラウザにはセッションを識別するCookieなどを渡します。
一方、JWTを利用する構成では、JWT自体に必要なClaimを含め、署名などを検証することでリクエストを処理できるよう設計することがあります。
| 比較項目 | JWTを利用した構成 | セッション認証 |
|---|---|---|
| 認証状態に関する情報 | トークンのClaimとして保持可能 | 主にサーバー側で管理 |
| サーバー側の状態管理 | 設計によっては少なくできる | セッション情報の管理が必要 |
| APIとの相性 | 利用されることが多い | 利用可能 |
| 即時失効 | 設計上の工夫が必要な場合がある | サーバー側で制御しやすい |
| トークン・IDの管理 | JWTを安全に管理する必要がある | セッションIDを安全に管理する必要がある |
ただし、「JWTなら必ずステートレス」「セッションなら必ずステートフル」と単純に分けられるわけではありません。
JWTの失効管理などのためにサーバー側で状態を持つ設計もあります。
JWTを利用するメリット
APIで扱いやすい
JWTはコンパクトなトークン形式として設計されているため、HTTPを利用するAPIなどで扱いやすい特徴があります。
フロントエンドとバックエンドを分離したWebアプリケーションや、複数のサービスからAPIへアクセスするシステムなどで利用できます。
Claimをトークンに含められる
JWTにはユーザーやトークンに関する情報をClaimとして含めることができます。
たとえばユーザーを識別する情報や、発行者、有効期限、対象となるシステムなどを表現できます。
署名を検証できる
署名付きJWTでは、受け取った側が署名を検証することで、トークンが正当な鍵によって署名されていることや、署名後に内容が変更されていないことを確認できます。
JWTを利用する際の注意点
JWTは便利な仕組みですが、適切に実装しなければセキュリティ上の問題につながります。
有効期限を適切に設定する
アクセストークンとしてJWTを利用する場合、必要以上に長い有効期限を設定すると、トークンが漏えいした際のリスクが大きくなります。
システムの要件に応じて適切な有効期限を設計する必要があります。
署名アルゴリズムを適切に検証する
JWTのHeaderにはalgというパラメータがあります。
JWTのセキュリティに関するベストプラクティスを定めたRFC 8725では、アプリケーション側で許可するアルゴリズムを指定し、それ以外を受け入れないことなどが求められています。
受信したJWTの情報だけを信用してアルゴリズムを決定するような実装は避ける必要があります。
Claimを検証する
署名が正しいからといって、そのJWTを無条件に受け入れてよいわけではありません。
用途に応じて、iss、aud、exp、nbfなどのClaimを適切に検証することが重要です。
たとえばaudを確認することで、そのJWTが自分のアプリケーションを対象として発行されたものなのかを確認できます。
JWTの保存場所を慎重に設計する
WebブラウザでJWTなどの認証情報をどこに保存するかは、セキュリティ上重要な設計事項です。
特にJavaScriptからアクセスできるlocalStorageやsessionStorageに認証トークンを保存すると、XSS(クロスサイトスクリプティング)が発生した際にトークンを盗まれる危険があります。
ブラウザアプリケーションでは、システムの構成や脅威モデルに応じて、HttpOnly・Secure・SameSite属性を適切に設定したCookieやBFF(Backend for Frontend)などを含めて保存方法を検討する必要があります。
ログアウトとトークン失効を考える
JWTに有効期限が設定されている場合でも、ユーザーのログアウトやアカウント停止などによって、有効期限より前にトークンを無効化したい場合があります。
完全にステートレスな構成では、すでに発行したJWTをサーバー側から即座に無効化することが難しい場合があります。
そのため、短い有効期限のアクセストークンを利用する、必要に応じて失効情報を管理するなど、システム要件に応じた設計が必要です。
JWTとアクセストークンは同じものではない
JWTについて理解するときに注意したいのが、「JWT=アクセストークン」ではないという点です。
JWTはトークンの形式です。
一方、アクセストークンは保護されたリソースへアクセスするために使用される認可情報です。
アクセストークンの形式としてJWTが採用されることはありますが、アクセストークンが必ずJWTであるとは限りません。
また、OpenID ConnectではID TokenにJWTが使用されます。
つまり、「JWT」「アクセストークン」「ID Token」はそれぞれ異なる概念として理解することが重要です。
JWT認証が利用される場面
JWTは、APIを中心としたシステムや複数サービス間でトークンを受け渡すシステムなどで利用されています。
たとえば、SPA(Single Page Application)のバックエンドAPI、モバイルアプリ向けAPI、マイクロサービス間の認証・認可基盤、OAuth 2.0やOpenID Connectを利用するシステムなどが挙げられます。
ただし、JWTを採用すれば必ずセッション方式より優れたシステムになるわけではありません。
一般的なWebアプリケーションでは、従来型のサーバー管理セッションがシンプルで適切な場合もあります。
システム構成やセキュリティ要件、失効管理の必要性などを考慮して選択することが重要です。
JWT認証を理解するときのポイント
JWTについては、「認証方式」だけでなく「トークン形式」として理解すると整理しやすくなります。
JWTはJSON形式のClaimを扱うための標準化されたトークン形式であり、署名付きJWTでは署名によって完全性や真正性を検証できます。
一方で、一般的な署名付きJWTのPayloadは暗号化されているわけではありません。
また、安全に利用するには署名の検証だけではなく、有効期限、発行者、AudienceなどのClaimを用途に応じて適切に検証する必要があります。
JWTの仕組みを正しく理解し、「JWTだから安全」「JWTだからステートレス」と単純に考えず、システム全体の認証・認可・トークン管理を設計することが重要です。
まとめ
JWT(JSON Web Token)は、JSON形式のClaimをコンパクトにやり取りするための標準化されたトークン形式です。
JWTを認証後のトークンとして利用するシステムでは、ログイン成功後にJWTを発行し、その後のAPIリクエストでトークンを提示して、サーバー側で署名やClaimを検証する仕組みを構築できます。
JWTはAPIや分散システムで便利な一方、Payloadが必ずしも暗号化されているわけではないこと、有効期限や発行者などのClaimを適切に検証する必要があること、トークンの保存・漏えい・失効について考慮する必要があることなど、セキュリティ上の重要なポイントがあります。
JWTを採用するときは単なる「ログイン用トークン」としてではなく、JWS・JWE、アクセストークン、OAuth 2.0、OpenID Connectなどとの関係も理解したうえで適切に設計することが大切です。


コメント