IT用語集

JWTとは? わかりやすく10分で解説

水色の背景に六角形が2つあるイラスト 水色の背景に六角形が2つあるイラスト
アイキャッチ
目次

はじめに

デジタル化が進むほど、オンライン上で「誰が」「何に」アクセスできるかを正しく制御する重要性は増していきます。特にWebアプリやAPI連携では、認証・認可の仕組みが複雑化しやすく、実装の選択を誤ると不正アクセスや情報漏えいの原因になりかねません。本記事では、こうした課題の解決に使われることが多いJWT(JSON Web Token)について、仕組み・使い方・安全に運用するための注意点まで整理し、導入すべきか判断できる状態を目指します。

JWTとは

JWT(JSON Web Token)は、JSON形式の情報(クレーム)を安全にやり取りするためのトークン仕様で、標準化された仕様(RFC 7519)として広く利用されています。JWTは「ヘッダー」「ペイロード」「署名」の3要素をドット(.)で連結した文字列で表現し、各要素はBase64urlでエンコードされます。

ここで重要なのは、JWTは「暗号化された秘密の塊」ではなく、基本形(JWS)では中身はデコードして読めるという点です。JWTは主に改ざんされていないこと(完全性)を署名で保証します。中身を秘匿したい場合は、暗号化(JWE)や、そもそも機密情報を入れない設計が必要です。

JWTの必要性と利点

JWTが利用される背景には、「サーバーが状態(セッション)を持たない設計に寄せたい」「多数のAPIやサービス間で認証情報を持ち運びたい」といった要件があります。JWTはトークン自体にクレームを含められるため、設計次第ではサーバー側でセッション情報を保持せずに認証状態を扱えます。

ただし、ここも誤解が起きやすいポイントです。JWTを使うと必ず“セッション不要”になるわけではありません。例えば、ログアウトを確実に反映したい、漏えい時に即時無効化したい、強制失効や端末単位の管理が必要、といった要件がある場合は、サーバー側でトークンの状態(失効リスト、トークン管理DB、リフレッシュトークン管理など)を持つ運用が現実的です。

JWTの利点は、軽量な文字列として扱いやすく、HTTPヘッダー(Authorization: Bearer ...)などで運べること、署名により改ざん検知ができること、サービス間連携やAPI認可で扱いやすいことにあります。一方で、後述する通り「保存方法」「失効」「アルゴリズム選択」「クレーム設計」を誤ると、利便性がそのままリスクになります。

JWTの基本的な構造

JWTは主に3つの部分から構成されています。Header(ヘッダー)、Payload(ペイロード)、Signature(署名)です。この3つが連携して、トークンの種類・中身・改ざん検知(完全性)を成立させています。

JWTの3つの部分

Headerは、トークンの種類(typ)や署名アルゴリズム(alg)などを示します。典型的には、algにHS256(共有鍵)やRS256(公開鍵暗号)などが入ります。

Payloadには、トークンに含めたい情報(クレーム)が入ります。クレームは一般に、標準でよく使われる登録済みクレーム(例:iss, sub, aud, exp, iat, nbf, jti)と、アプリ固有のクレームに分けて設計します。ここに「権限」や「ユーザー属性」などを入れることも可能ですが、入れすぎると漏えい時の被害が増えるため、必要最小限が基本です。

Signatureは、ヘッダーとペイロードが改ざんされていないことを確認するためのものです。署名は「ヘッダーとペイロードを結合したもの」に対して、共有鍵(HS系)または秘密鍵(RS/ES系)で生成されます。受信側は署名を検証し、改ざんされていないことを確認できます。

なお、ここでいう「署名」は暗号化ではありません。署名は改ざん検知を目的とするため、JWTをデコードするとペイロードは読み取れます。機密情報を入れない理由がここにあります。

各部分の目的と役割

Headerは「どう検証すべきか」の手がかりです。ただし、Headerに書かれたalgを鵜呑みにする実装は危険です。後述の通り、受信側は許可するアルゴリズムを固定し、想定外のアルゴリズムを拒否する必要があります。

Payloadは「何を主張しているか」を表し、認証・認可の判断材料になります。ただし、署名検証ができていないPayloadは信頼できません。受信側は、署名検証と合わせて、有効期限(exp)、発行者(iss)、対象(aud)などの妥当性を検証しなければなりません。

Signatureは「改ざんされていない」ことを保証しますが、署名が正しくても「トークンが盗まれていない」ことまでは保証できません。盗まれたトークンは、正しく署名されている限り、そのまま悪用される可能性があります。これがJWT運用の最大の落とし穴の一つです。

JWTの使い方

JWTの運用で押さえるべきプロセスは、生成検証です。さらに、実務では「どこに保存するか」「いつ更新するか」「どう失効させるか」まで設計して初めて安全に運用できます。

JWTの生成

JWTの生成は、各言語のライブラリを使うのが一般的です。重要なのは、単に署名して発行するだけでなく、必要なクレームを適切に設定することです。例えば、以下は多くのシステムで検討対象になります。

  • exp(有効期限):短めを基本にし、更新設計とセットで考えます。
  • iat(発行時刻)/nbf(有効開始):時刻の扱いを明確にします。
  • iss(発行者)/aud(対象):トークンの出所と用途の取り違えを防ぎます。
  • jti(ID):失効管理や重複検知をしたい場合に有効です。

「何でもPayloadに入れて便利にする」という方向に寄せると、漏えい時の被害が増えます。JWTは“持ち歩ける”からこそ、入れる情報は絞る設計が安全です。

JWTの検証方法

検証は、受信側(APIやバックエンド)が必ず行うべき処理です。チェックすべきポイントは「形式」「署名」「クレームの妥当性」です。

  • 形式:3要素(ヘッダー.ペイロード.署名)になっているか
  • 署名検証:想定した鍵・想定したアルゴリズムで検証できるか
  • 有効期限:expが切れていないか(時刻ずれの許容幅も含める)
  • 発行者・対象:iss / audが想定通りか
  • その他:必要に応じてjtiの失効確認、権限クレームの妥当性確認など

ここで「検証はライブラリがやってくれるから大丈夫」と考えるのは危険です。ライブラリがどこまで検証しているか(iss/audまで見るか、algを固定しているか)は実装次第です。受信側で「検証ポリシー」を明示し、チェック漏れを防ぐことが重要です。

JWTの利用例: 認証と認可

JWTは、認証(Authentication)と認可(Authorization)の両方で使われます。ただし役割を混同すると設計が崩れます。

  • 認証:ログインなどで本人確認を行い、トークンを発行する(誰かを確定する)
  • 認可:トークンのクレームを参照し、アクセス権を判断する(何を許可するか)

APIでは、クライアントがAuthorizationヘッダーでJWTを提示し、サーバーが検証してリクエストを許可する、という流れが一般的です。セッション管理にも使われますが、後述の通り「ログアウト」や「即時無効化」をどう実現するかが実務の分岐点になります。

JWTを安全に使うためのベストプラクティス

JWTの安全性は「仕様」よりも「運用」で決まります。ここでは、誤解の多いポイントを中心に、実務で落とし穴になりやすい点を整理します。

秘密鍵・署名鍵の安全な管理

原稿では「パスワードのハッシュ化」という見出しになっていましたが、JWT運用で重要なのは署名に使う鍵(共有鍵または秘密鍵)を安全に管理することです。署名鍵が漏えいすると、攻撃者が正規のJWTを偽造できるため、被害は重大になります。

具体的には、鍵をコードに直書きしない、環境変数やシークレット管理基盤で保護する、鍵のローテーション(定期更新)を前提に設計する、といった対策が基本です。パスワードのハッシュ化はユーザー認証側で重要な話題ですが、JWTの署名鍵を「ハッシュ化して保存すれば安全」という整理にはなりません。鍵はハッシュ化しても署名・検証に使えなくなるため、そもそも“秘匿しつつ使える形”で保護する設計が必要です。

トークンの有効期限設定

JWTの有効期限(exp)は、短いほど漏えい時の被害を抑えやすい一方、短すぎるとユーザー体験が悪化します。このジレンマを解消する代表的な設計が、短命のアクセストークン + 長命のリフレッシュトークンです。

アクセストークンは短い期限にして漏えいリスクを下げ、リフレッシュトークンはサーバー側で管理して失効できるようにします。これにより「短命なのに使い勝手が悪くない」「緊急時にリフレッシュトークンを失効できる」という運用が可能になります。

HTTPS上でのトークン送信

JWTを扱う場合、通信経路の保護は必須です。HTTPSで暗号化されていないと、盗聴でトークンが漏えいし、そのままなりすましに悪用される可能性があります。特に公共Wi-Fiやプロキシ環境などではリスクが高まります。

また、送信経路だけでなく、クライアント側の保存方法も重要です。ブラウザでlocalStorageに保存 said などはXSSで抜かれやすい、Cookieで運ぶならHttpOnly/SameSite/Secureなどの設計が必要、など、システム形態に応じた対策が求められます。

署名アルゴリズムと検証ポリシーの固定

JWTでよく知られる落とし穴に、「none」アルゴリズム問題があります。受信側がヘッダーのalgを無条件に受け入れる実装だと、署名なしのトークンが通ってしまう恐れがあります。

対策の基本は、受信側で許可するアルゴリズムを固定し、想定外のalgを拒否することです。また、HS系(共有鍵)とRS系(公開鍵暗号)を混在させる場合は、鍵の扱いを誤ると検証が破綻します。仕様を理解したうえで、運用する方式を絞るのが安全です。

JWTの解析

JWTはデコードすると中身が読めるため、解析自体は難しくありません。ただし、読めることと信頼できることは別です。解析のポイントは「デコード」と「検証」を分けて考えることにあります。

トークンのデコード方法

JWTはBase64urlでエンコードされているため、オンラインデコーダーやライブラリで簡単にデコードできます。ここで得られる情報は、署名検証をしていない限り、攻撃者が改ざんした可能性があるため信頼できません。運用上は、デコードした内容を“参考”にするのは構いませんが、認可判断に使う場合は必ず署名検証とクレーム検証が必要です。

「なりすまし」攻撃対策

JWTが盗まれたり偽造されたりすると、攻撃者が正当なユーザーになりすます恐れがあります。偽造対策としては署名検証とアルゴリズム固定が中心です。一方、盗難対策としては有効期限を短くする、保存先を安全にする、リフレッシュトークンをサーバー管理する、必要に応じてjtiで失効管理する、といった多層の設計が重要になります。

よく使われる署名方式としてHS256やRS256などがありますが、「強いアルゴリズムを使えば安心」とは言い切れません。鍵管理・検証ポリシー・運用設計が弱いと、強いアルゴリズムでも破綻します。JWTはあくまで道具であり、運用の設計が安全性を左右します。

JWTの応用

JWTは「認証・認可のトークン」として理解されがちですが、実務ではシステム構成に応じた応用が行われます。ただし、何でもJWTで解決しようとすると、失効や漏えい対策が追い付かなくなります。用途ごとに適用可否を判断することが重要です。

多要素認証における利用

多要素認証(MFA)そのものをJWTが“実現する”わけではありませんが、MFAの結果をトークンとして表現し、後続のAPI呼び出しに引き継ぐ用途で使われることはあります。例えば、「MFA完了済み」を示すクレームをアクセストークンに含め、重要操作ではそのクレームが必須、という認可設計が考えられます。

ただし、SMSの一時コードをJWTで送る、といった設計は誤解を招きやすく、実装も複雑になります。MFAは認証フロー(ワンタイムコードやFIDO2など)として実装し、JWTは「認証結果を運ぶトークン」として扱う、という役割分担が安全です。

マイクロサービス間の情報共有

マイクロサービス環境では、サービス間通信でも「誰(どのサービス)が呼んでいるか」「どこまで許可するか」を判定する必要があります。JWTを使うと、サービス間呼び出しの際にトークンを提示し、受信側が署名とクレームを検証して認可する、といった構成が組みやすくなります。

ただし、ここでも「ステートレスだから安心」とはなりません。トークンが漏えいした場合の影響はサービス間で広がるため、期限・スコープ(権限範囲)・発行対象(aud)・発行者(iss)を厳格に設計し、必要に応じて失効やローテーションも含めた運用が必要です。

JWTの限界と注意点

JWTは便利ですが、すべての認証課題を解決する万能薬ではありません。むしろ「扱いやすいからこそ、誤用しやすい」技術です。ここでは、誤用が起きやすいポイントを具体的に整理します。

JWTの誤用におけるリスク

JWTが盗まれると、攻撃者は正規ユーザーになりすましてアクセスできる可能性があります。これはJWTが「ベアラートークン」として運用されることが多く、提示できた者が正当という性質を持つためです。

また、JWTは一度発行すると、単純な構成では有効期限まで使われ続けます。緊急時に即時無効化したい場合は、失効リストやトークン管理、リフレッシュトークン管理など、サーバー側の状態管理が必要になります。

さらに、暗号・署名方式の選定や実装が不適切だと、署名検証が破られたり、アルゴリズム混同などの脆弱性につながる恐れがあります。JWTは仕様がシンプルに見えますが、運用要件まで含めると設計論点は多い、という前提で扱うべきです。

JWTとセッションの比較

JWTとセッションは、優劣ではなく「どの要件を優先するか」で選択が変わります。

観点JWTセッション
状態管理設計次第でステートレスにできるサーバー側で状態を保持する
即時無効化単純構成では難しい(失効管理が必要)サーバー側で無効化しやすい
スケールサービス間で扱いやすい共有ストアなどの設計が必要
漏えい時の影響トークン有効期限・保存方法に強く依存セッションID盗難対策は必要だが運用で制御しやすい

JWTは「クロスオリジンで共有できる」といった表現がされることがありますが、実際にはCORSやCookieの属性、トークンの保存方式などの設計が絡みます。JWTは“持ち運べる”がゆえに、使い方を誤るとリスクも持ち運んでしまう点に注意が必要です。

まとめ

JWTは、JSON形式のクレームを持ち運べるトークン仕様で、署名により改ざん検知(完全性)を実現します。ヘッダー・ペイロード・署名の3要素で構成され、API認可やサービス間連携などで広く使われています。一方で、JWTは暗号化ではないため中身は読めること、盗まれたトークンは悪用され得ること、単純構成では即時失効が難しいことなど、運用上の注意点があります。

安全に使うには、署名アルゴリズムの固定と厳密な検証、鍵管理、短命トークンと更新設計、クレーム設計の最小化、保存方法と送信経路(HTTPS)の対策などをセットで考える必要があります。JWTを採用するかは「ステートレス化したい」「サービス間で認可情報を運びたい」といった利点だけでなく、「失効や漏えい時の対処をどう設計するか」まで含めて判断することが重要です。

Q.JWTは暗号化されていますか?

一般的なJWT(署名付き)は暗号化ではなく、デコードすれば中身を読めます。

Q.JWTの署名は何を保証しますか?

ヘッダーとペイロードが改ざんされていないことを保証します。

Q.JWTを使うとセッションは不要になりますか?

要件次第です。即時失効などが必要ならサーバー側の状態管理が必要になります。

Q.JWTに入れてはいけない情報はありますか?

機密情報は原則入れず、必要最小限のクレームに絞るのが安全です。

Q.受信側で必ず検証すべき点は何ですか?

署名、有効期限、発行者、対象、想定アルゴリズムの固定などです。

Q.有効期限は短い方がよいですか?

短い方が漏えい時の被害を抑えやすいですが、更新設計とセットで決めます。

Q.ログアウトを確実に反映するにはどうしますか?

失効管理やリフレッシュトークン管理など、サーバー側で無効化できる設計が必要です。

Q.「none」アルゴリズム問題とは何ですか?

署名なしトークンが通る実装があり得るため、受信側でアルゴリズムを固定して拒否します。

Q.JWTはどこに保存するのが安全ですか?

要件次第ですが、XSS対策を考えるならHttpOnly Cookieなどの設計が検討されます。

Q.JWTとセッションはどちらが良いですか?

即時失効や管理性はセッションが有利で、分散連携や持ち運びはJWTが有利です。

記事を書いた人

ソリトンシステムズ・マーケティングチーム