JWTとは?構造・署名検証の仕組みとセッション・OAuth/OIDCとの違いを実装視点で解説
JWT(JSON Web Token)は、JSON形式の情報を署名付きでコンパクトに運ぶトークンの仕様で、RFC 7519として標準化されています。ドットで区切られた3つのパーツにヘッダー・ペイロード・署名を収め、受け取った側が署名を検証するだけで改ざんの有無を判定できるのが特徴です。この記事では、JWTの構造とBase64URL、HS256/RS256の署名検証、alg:noneなどの攻撃への対策、トークンの保存場所と失効の設計、そしてサーバセッションやOAuth 2.0・OIDCとの違いと使い分けまでを、実装者が設計判断できる粒度で整理します。API認証や会員基盤にJWTを組み込む開発者が対象です。
目次
まとめ:JWTは署名付きで検証できるトークンの器と実装の要点
JWTは、発行者が秘密鍵または共有鍵で署名したJSONを、受信側が対応する鍵で検証してデータの正当性を確かめるトークンです。各パーツはBase64URLで変換されているだけで暗号化ではないため、ペイロードは誰でも読めます。パスワードや個人情報をそのまま載せない前提で設計します。
実装の勘所は3つに集約できます。1つ目は署名検証で、期待するアルゴリズムをサーバ側で固定し、トークンのヘッダーが名乗るalgを鵜呑みにしないこと。2つ目は失効の弱さへの備えで、JWTはサーバに状態を持たないぶん個別の無効化が難しいため、有効期限を短く切りリフレッシュトークンと組み合わせます。3つ目は保存場所の判断で、localStorageはXSS、Cookieはクロスサイトの偽装リクエストという別々のリスクを抱えるため、httpOnly・SameSite・短命化で守り方を決めるのが定石です。JWT自体はトークンの器であり、OAuth 2.0やOIDCといったプロトコルの中で運ばれる部品だと捉えると、役割の切り分けが見通せます。
JWTの構造:ヘッダー・ペイロード・署名の3パーツとBase64URL
JWTを理解する近道は、1本の文字列がどう組み立てられているかを分解して見ることです。xxxxx.yyyyy.zzzzzのようにドットで3分割された各部が、それぞれ別の役割を持ちます。
ドットで区切られた3パーツの構成とBase64URL変換の仕組み
JWTは、ヘッダー・ペイロード・署名の3つをドットでつないだ文字列です。先頭2つはそれぞれのJSONをBase64URLで変換したもので、末尾の署名はその2つを連結して鍵で計算した値になります。Base64URLはURLやHTTPヘッダーで安全に扱える文字だけを使う変換方式で、通常のBASE64とは一部の記号の扱いが異なります。
ここで押さえるべきは、Base64URLが暗号化ではなく単なる変換だという点です。ヘッダーとペイロードはデコードすれば中身が読めるため、機密情報を平文で入れると漏えいします。中身を隠したい場合は、署名のみのJWS形式ではなく暗号化を伴うJWE形式を選ぶか、機密データ自体をトークンに載せない設計にします。一般に「JWT」と呼ばれるのは署名付きで中身は読めるJWS形式を指すことがほとんどです。
ヘッダーとペイロードの構造と登録済みクレームの設計で押さえる点
ヘッダーには、トークン種別を示すtypと署名アルゴリズムを示すalgが入ります。ペイロードには「クレーム」と呼ばれる情報の断片を並べ、RFC 7519があらかじめ意味を決めた登録済みクレームを使うのが基本です。独自の項目を足すこともできますが、他規格との衝突を避けるため命名には配慮します。
実装で扱う頻度が高い登録済みクレームは次のとおりです。値を検証に使う前提で設計します。
| クレーム | 意味 | 用途 |
|---|---|---|
| iss | 発行者 | 発行元の確認 |
| sub | 主体 | ユーザー識別 |
| aud | 宛先 | 受け手の限定 |
| exp | 有効期限 | 失効の判定 |
| nbf | 有効開始 | 利用開始の制御 |
| jti | 一意ID | 再送の検知 |
ペイロードは軽く保つのが原則です。トークンはリクエストごとに送られるため、権限判定に不要な属性まで詰め込むと通信量が膨らみます。認可に必要な最小限の識別子と権限だけを載せ、詳細はサーバ側で引く設計にすると取り回しが軽くなります。
JWTの署名検証フローとHS256・RS256による鍵方式の使い分け
JWTの安全性は、発行と検証の両側が同じ鍵体系を正しく扱えるかにかかっています。ここを緩めると、偽造トークンを受け入れる致命的な穴です。まず処理の流れを押さえ、次に鍵方式の選択に進みます。
発行から検証までの署名照合とクレーム確認を両輪でそろえる流れ
サーバはログイン認証が成功すると、ユーザーIDや権限をペイロードに詰め、鍵で署名したJWTをクライアントへ返します。クライアントは以降のリクエストで、多くはAuthorizationヘッダーにBearerトークンとしてこれを添える形です。サーバは受け取ったトークンを検証してからリクエストを処理する流れになります。検証の順序は次のとおりです。
- トークンをドットで3分割する
- ヘッダーとペイロードから署名を再計算する
- 付与された署名と一致するか照合する
- expやiss、audなどのクレームを検証する
署名照合と有効期限の確認は、どちらか一方でも欠けると防御になりません。署名が通ってもexpを見なければ期限切れトークンを受け入れてしまい、expだけ見ても署名を検証しなければ偽造を素通りさせます。両輪でそろえて初めて検証が成立します。
HS256(共通鍵)とRS256・ES256(公開鍵)の判断基準
署名方式は大きく2系統に分かれます。HS256はHMACによる共通鍵方式で、発行と検証が同じ秘密鍵を共有します。RS256やES256は公開鍵暗号方式で、発行側だけが持つ秘密鍵で署名し、検証側は公開鍵で確かめる仕組みです。
| 方式 | 鍵 | 向く構成 |
|---|---|---|
| HS256 | 共通鍵 | 単一サービス内 |
| RS256 | 公開鍵ペア | 複数サービス連携 |
| ES256 | 楕円曲線鍵 | 鍵を小さく保つ構成 |
選択の分岐は、鍵をどこまで配るかで決まります。発行と検証が同じサービス内で完結するならHS256が単純で扱いやすい選択です。逆に、認証サーバが発行したトークンを別のマイクロサービスやフロントで検証する構成では、秘密鍵を配り歩かずに公開鍵だけを配布できるRS256やES256が向きます。検証側に共通鍵を渡すと、その鍵で誰でもトークンを偽造できてしまうため、複数サービスをまたぐならHMAC系は避けるのが堅実です。
JWTのセキュリティ実装:alg:none・保存場所・失効の設計
JWTの事故の多くは、仕様の理解不足に起因する実装の抜けから起きます。RFC 8725(JWT BCP、2020年)にも対策がまとめられており、ここでは実務で外せない3つの論点を具体的に示します。自社サービスへ認証を組み込む設計段階で判断材料にしてください。
alg:noneとアルゴリズム混同攻撃を防ぐ検証ロジックの固め方
もっとも古典的な穴がalgの扱いです。JWTの仕様には署名なしを意味するnoneがあり、検証側がヘッダーのalgをそのまま信じると、攻撃者がalgをnoneに書き換えた無署名トークンを受け入れてしまいます。さらに、RS256を期待するサーバにHS256のトークンを送り、公開鍵を共通鍵として使わせて署名を通す混同攻撃も知られています。
対策は共通していて、検証側で許可するアルゴリズムをホワイトリストで固定し、トークンが名乗るalgを判断材料にしないことです。ライブラリの検証関数には期待するアルゴリズムを明示的に渡し、noneや想定外の方式は問答無用で拒否します。検証ロジックを自作せず、実績あるJWTライブラリの最新版に任せる判断が現実的な守りになります。
トークンの保存場所とXSS・CSRFのリスクのトレードオフ判断
発行したJWTをクライアントのどこに置くかも設計判断です。JavaScriptから読めるlocalStorageに保存すると実装は楽ですが、XSSでスクリプトが混入した瞬間にトークンを盗まれます。一方、httpOnly属性を付けたCookieに入れればJavaScriptからは読めなくなるものの、今度はブラウザが自動送信する性質を突かれるクロスサイトの偽装リクエストへの備えが要ります。
現実的な落としどころは、httpOnly・Secure・SameSite属性を付けたCookieに置き、状態変更を伴う操作にはCSRFトークンを併用する組み合わせです。どちらの保存先を選んでも、有効期限を短く切っておけば盗まれた際の被害窓口を狭められます。「XSSとCSRFのどちらを主リスクと見るか」を先に決め、それに応じて保存先と付随対策をそろえるのが設計の順序になります。
ステートレスゆえの失効の弱さとリフレッシュトークンによる補完
JWTの利点であるステートレス性は、失効の面では弱点に転じます。サーバがトークンの一覧を持たないため、発行済みのJWTを個別に無効化するのが難しく、期限が切れるまで有効なままになります。ログアウトやアカウント停止を即座に反映したい要件とは相性が良くありません。
この弱点を埋める定番が、短命なアクセストークンと長命なリフレッシュトークンの二段構えです。アクセス用のJWTは数分から十数分で失効させ、切れたらリフレッシュトークンで再発行します。リフレッシュトークン側はサーバで管理して失効を効かせ、必要な場面で無効化できるようにするのが役割です。即時失効が厳格に要る領域では、短命JWTにサーバ側のブロックリスト照合を足す設計も選択肢になります。
JWTとセッション・OAuth 2.0・OIDCの関係と使い分け
JWTを検討すると必ず、従来のサーバセッションとの比較や、OAuth 2.0・OIDCとの関係で迷いが生じます。3者は層が異なるため、境界を取り違えると設計が絡まりがちです。ここを整理して選定の判断につなげます。
サーバセッションとJWTのステートフルとステートレスの比較観点
従来のセッション方式は、サーバがセッションIDと本人情報の対応をサーバ側で保持し、クライアントにはIDだけを渡します。状態をサーバが握るため失効は容易な半面、サーバを増やす際にはセッション情報の共有が必要です。JWTは逆で、必要な情報をトークン自体に持たせて状態を持たないため、水平スケールしやすいかわりに個別失効が難しくなります。
| 観点 | サーバセッション | JWT |
|---|---|---|
| 状態 | サーバが保持 | トークンが保持 |
| 失効 | 即時に可能 | 個別は困難 |
| スケール | 共有が必要 | 横展開が容易 |
この対比から、単一サーバで完結する一般的なWebアプリのログイン維持なら、素直なサーバセッションのほうが失効の扱いで有利な場面が多くあります。JWTが生きるのは、サービスをまたぐAPI認証や、状態共有を避けたい分散構成です。
JWTはトークンの器・OIDCのIDトークンはJWTという関係
JWTとOAuth 2.0・OIDCは同じ層の競合ではありません。JWTは「情報を署名付きで運ぶ器」の仕様で、OAuth 2.0(RFC 6749)はアクセス権限を委譲する認可の枠組み、OIDCはそのOAuth 2.0の上に認証層を足したプロトコルです。OIDCが発行するIDトークンは、実体がまさにJWTです。つまりJWTはプロトコルの中で使われる部品にあたります。
それぞれの仕組みは個別記事で扱っています。API権限の委譲フローはOAuth 2.0とは?仕組み・認可フローと認証・認可の違いをわかりやすく解説を、OAuth 2.0の上でIDトークン(JWT)をどう発行するかはOIDC(OpenID Connect)とは?仕組み・OAuthとの違いをわかりやすく解説を参照してください。JSONではなくXMLで認証情報を運ぶ企業SSO向けの規格についてはSAMLとは?認証フロー・IdP/SPの仕組みとOAuth・OIDCとの使い分けを実装視点で解説で扱っており、JWTを使うOIDCとの対比で選定の見取り図になります。
JWTを採用すべき場面と見送るべき場面の条件付きでの切り分け
採用判断は条件で言い切れます。フロントとAPIが分離したSPAやモバイルアプリ、複数サービスをまたぐAPI認証、外部のOIDCプロバイダと連携する構成では、ステートレスで自己完結するJWTが素直な選択です。短命なアクセストークンとして使う限り、失効の弱点も運用でカバーできます。
逆に、単一サーバで動く従来型のWebアプリで、ログアウトやアカウント停止を即座に効かせたい要件が中心なら、JWTを無理に使わずサーバセッションを選んだほうが設計は素直です。「状態をサーバに持ちたくないか、即時失効を重く見るか」を最初の分岐に置くと、遠回りを避けられます。JWTベースの認証や会員基盤の設計・実装は、会員管理システム開発としてトークン運用や失効設計ごと受託しています。要件整理の段階からご相談ください。
よくある質問
JWTの導入検討でよく挙がる疑問を、実装者の視点で簡潔にまとめます。
JWTのペイロードは暗号化されていますか?
されていません。ヘッダーとペイロードはBase64URLで変換されているだけで、デコードすれば誰でも中身を読めます。JWTが守るのは改ざんの検知であって秘匿ではないため、パスワードや個人情報をペイロードに平文で載せてはいけません。中身を隠す必要があるときは、暗号化を伴うJWE形式を使うか、機密データ自体をトークンに含めない設計にします。
JWTとセッションはどちらを使うべきですか?
要件で分かれます。単一サーバでの一般的なログイン維持や、ログアウトを即座に反映したい用途はサーバセッションが素直です。複数サービスをまたぐAPI認証や、状態共有を避けたい分散構成ではJWTが向きます。JWTを使う場合も、有効期限を短く切りリフレッシュトークンと組み合わせる前提で設計します。
JWTを無効化(ログアウト)するにはどうしますか?
JWTはサーバに状態を持たないため個別失効が難しく、基本は有効期限切れを待ちます。即時に失効させたい場合は、アクセス用JWTを短命にしてリフレッシュトークン側をサーバ管理で無効化するか、失効させたいトークンのjtiをブロックリストに載せて検証時に照合する方法をとります。
HS256とRS256はどちらを選べばよいですか?
鍵をどこまで配るかで決まります。発行と検証が同じサービス内で完結するなら共通鍵のHS256が単純です。認証サーバが発行したトークンを別のサービスやフロントで検証するなら、秘密鍵を配らずに済む公開鍵方式のRS256やES256を選びます。検証側に共通鍵を渡すとその鍵で偽造できるため、サービスをまたぐ構成でHS256は避けます。
JWTとOAuth・OIDCの違いは何ですか?
層が異なります。JWTは情報を署名付きで運ぶトークンの器の仕様、OAuth 2.0はアクセス権限を委譲する認可の枠組み、OIDCはOAuth 2.0の上に認証層を足したプロトコルです。OIDCが発行するIDトークンの実体はJWTであり、JWTはこれらのプロトコルの中で使われる部品という関係になります。
関連記事
- OAuth 2.0とは?仕組み・認可フローと認証・認可の違いをわかりやすく解説:JWTが運ばれる「認可」の枠組み。アクセストークンの発行と権限委譲を実装視点で解説しています。
- OIDC(OpenID Connect)とは?仕組み・OAuthとの違いをわかりやすく解説:IDトークンの実体がJWT。OAuth 2.0の上で認証をどう足すかを整理しています。
- SAMLとは?認証フロー・IdP/SPの仕組みとOAuth・OIDCとの使い分けを実装視点で解説:JSONではなくXMLで認証を運ぶ企業SSO規格。JWTを使うOIDCとの対比で選定の参考になります。