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

JWT(JSON Web Token)は、JSON形式の情報(クレーム)をやり取りするためのトークン仕様で、RFC 7519として標準化されています。JWTは「JWS(署名またはMAC)」や「JWE(暗号化)」といった形で扱われるのが一般的で、署名付き(JWS)のJWTは「ヘッダー」「ペイロード」「署名」の3要素をドット(.)で連結した文字列として表現されます。一方、暗号化(JWE)のJWTは構造が異なり、用途(署名か暗号化か)によって見え方が変わります。なお、各要素はBase64urlでエンコードされます。
ここで押さえておきたいのは、JWTは「暗号化された秘密情報のかたまり」ではない、という点です。一般的な署名付き(JWS)のJWTでは、中身はデコードすれば読めます。署名やMACは、主に改ざんされていないこと(完全性)を保証するための仕組みです。中身を秘匿したい場合は暗号化(JWE)を使うか、そもそも機密情報を入れない設計が求められます。
JWTが利用される背景には、「サーバーが状態(セッション)を持たない設計に寄せたい」「複数のAPIやサービス間で認証情報を持ち運びたい」といった要件があります。JWTはトークン自体にクレームを含められるため、設計次第ではサーバー側でセッション情報を保持せずに認証状態を扱えます。
ただし、JWTを使えば必ず“セッション不要”になるわけではありません。ログアウトを即座に反映したい、漏えい時に強制的に無効化したい、端末単位で制御したい、といった要件がある場合は、サーバー側でトークンの状態(失効リストやトークン管理、リフレッシュトークン管理など)を持つ運用が現実的です。また、アクセスごとの検証がステートレスに寄っていても、実務では鍵の配布や更新、検証ポリシーの運用まで含めて設計する必要があります。
JWTの利点は、軽量な文字列として扱いやすく、HTTPヘッダー(Authorization: Bearer ...)などで運べる点や、完全性保護によって改ざん検知ができる点にあります。一方で、「保存方法」「失効」「アルゴリズム選択」「クレーム設計」を誤ると、その扱いやすさがそのままリスクになります。
JWTは、署名付きのJWSとして扱う場合、主に3つの部分から構成されます。Header(ヘッダー)、Payload(ペイロード)、Signature(署名)です。この3つが組み合わさることで、トークンの種類や中身、改ざん検知(完全性)が成り立ちます。なお、暗号化(JWE)として扱う場合は構造が異なるため、ここでは署名付きJWTを前提に整理します。
Headerには、トークンの種類(typ)や署名アルゴリズム(alg)などが記載されます。代表的な例としては、HS256(共有鍵)やRS256(公開鍵暗号)があります。
Payloadには、トークンに含めたい情報(クレーム)が入ります。標準でよく使われる登録済みクレーム(iss、sub、aud、exp、iat、nbf、jtiなど)と、アプリ固有のクレームを組み合わせて設計します。ここに権限やユーザー属性を入れることも可能ですが、入れすぎると漏えい時の影響が大きくなるため、必要最小限が基本です。
Signatureは、ヘッダーとペイロードが改ざんされていないことを確認するための要素です。これらを結合したデータに対し、共有鍵(HS系)や秘密鍵(RS/ES系)を用いて生成されます。受信側は署名を検証することで、内容が書き換えられていないことを確認できます。
なお、ここでいう「署名」は暗号化ではありません。デコードすればペイロードが読めるため、機密情報を入れない設計が重要になります。
Headerは「どのように検証すべきか」を示す手がかりです。ただし、Headerに記載されたalgをそのまま信用する実装は危険です。受信側では、許可するアルゴリズムを固定し、想定外のものを拒否する必要があります。
Payloadは「何を主張しているか」を表し、認証や認可の判断材料になります。ただし、署名検証が行われていないPayloadは信頼できません。受信側では、署名検証に加え、有効期限(exp)、発行者(iss)、対象(aud)などの妥当性を確認する必要があります。
Signatureは改ざん検知を担いますが、トークンが盗まれていないことまで保証するものではありません。盗まれたJWTは、署名が正しい限り、そのまま悪用される可能性があります。これはJWT運用で特に注意すべき点の一つです。
JWTの運用では、生成と検証が基本となります。加えて実務では、「どこに保存するか」「いつ更新するか」「どう失効させるか」まで含めて設計して初めて、安全な運用が可能になります。
JWTは各言語のライブラリを使って生成するのが一般的です。その際に重要なのは、単に署名して発行するだけでなく、必要なクレームを適切に設定することです。たとえば、以下のような項目は多くのシステムで検討対象になります。
「便利だから」と多くの情報をPayloadに入れると、漏えい時の影響が拡大します。JWTは持ち運べるからこそ、情報は絞り込む設計が重要です。
検証は、JWTを受け取る側(APIやバックエンド)が必ず行うべき処理です。確認すべきポイントは、「形式」「署名」「クレームの妥当性」です。
ライブラリ任せにすると、issやaudの検証、アルゴリズム固定が抜け落ちる場合があります。受信側で検証ポリシーを明示し、漏れが出ないようにすることが重要です。
JWTは認証(Authentication)と認可(Authorization)の両方で使われますが、役割を混同すると設計が複雑になります。
APIでは、クライアントがAuthorizationヘッダーでJWTを提示し、サーバーが検証してリクエストを許可する流れが一般的です。セッション管理に使う場合は、ログアウトや即時無効化をどう扱うかが設計上の分かれ目になります。
JWTの安全性は、仕様そのものよりも運用設計に大きく左右されます。ここでは、実務でつまずきやすいポイントを中心に整理します。
JWT運用で最も重要なのは、署名に使う鍵(共有鍵または秘密鍵)を適切に管理することです。鍵が漏えいすると、攻撃者が正規のJWTを偽造できてしまいます。
鍵をコードに直接書かない、シークレット管理基盤で保護する、定期的なローテーションを前提に設計する、といった対策が基本です。署名鍵は、秘匿しつつ運用で安全に使える形で管理する必要があります。
JWTの有効期限(exp)は、短いほど漏えい時の影響を抑えやすい一方、短すぎると使い勝手が悪くなります。このバランスを取る方法として、短命なアクセストークンと、長命なリフレッシュトークンを組み合わせる設計がよく採用されます。
アクセストークンは短期間で失効させ、リフレッシュトークンはサーバー側で管理・失効できるようにすることで、安全性と利便性の両立を図ります。
JWTは必ずHTTPS上で送信する必要があります。暗号化されていない通信では、盗聴によってトークンが漏えいし、そのままなりすましに使われる恐れがあります。
また、クライアント側での保存方法も重要です。ブラウザでlocalStorageに保存する方式はXSSで抜き取られやすく、Cookieで運ぶ場合はHttpOnlyやSameSite、Secure属性などを考慮した設計が求められます。
JWTでは、「none」アルゴリズム問題など、実装上の落とし穴が知られています。受信側がヘッダーのalgを無条件に受け入れると、署名なしトークンが通ってしまう可能性があります。
そのため、受信側では許可するアルゴリズムを固定し、想定外のものを拒否することが基本です。さらに、アルゴリズムごとに使用する鍵を明確に分け、想定外の組み合わせを許さない設計が重要です。
JWTは便利な仕組みですが、すべての認証課題を解決できる万能な技術ではありません。扱いやすい反面、誤った使い方をするとリスクも増えます。
JWTはベアラートークンとして使われることが多く、提示できた人が正当とみなされます。そのため、盗難時の影響が大きく、単純な構成では即時無効化が難しいという性質があります。
また、「JWTはクロスオリジンで共有できる」といった表現を目にすることがありますが、JWT自体がクロスオリジン共有を保証するわけではありません。実際の挙動は、保存方法や送信方法、ブラウザ側の制約(CORSやSameSiteなど)に依存します。
JWTは、JSON形式のクレームを持ち運べるトークン仕様で、改ざん検知による完全性保護を提供します。API認可やサービス間連携などで広く使われる一方、暗号化ではないため中身が読めること、盗まれたトークンは悪用され得ること、即時失効が難しいことなど、運用上の注意点があります。
安全に利用するには、アルゴリズムの固定と厳密な検証、鍵管理とローテーション、短命トークンと更新設計、クレームの最小化、保存方法と通信経路の対策を組み合わせて考える必要があります。JWTを採用するかどうかは、利便性だけでなく、失効や漏えい時の対処まで含めて判断することが重要です。
一般的な署名付きJWTは暗号化ではなく、デコードすれば中身を読めます。
ヘッダーとペイロードが改ざんされていないことを保証します。
要件次第で、即時失効などが必要な場合はサーバー側の管理が必要です。
機密情報は原則として含めず、必要最小限のクレームに絞ります。
署名、有効期限、発行者、対象、アルゴリズム固定などです。
漏えい時の影響は抑えられますが、更新設計とあわせて決めます。
失効管理やリフレッシュトークン管理など、サーバー側で無効化できる設計が必要です。
署名なしトークンが通る実装を防ぐため、アルゴリズムを固定します。
要件次第ですが、XSS対策を考えるとHttpOnly Cookieが検討されます。
即時無効化や管理性はセッション、分散連携や持ち運びはJWTが向いています。