JWT
JWT(JSON Web Token)は、インターネット上で情報を安全に送受信するためのオープンな標準規格です。主に認証や情報交換のために使われます。
JWTの構成要素
JWTは、ピリオド(.
)で区切られた3つの要素で構成されています。
-
ヘッダー (Header):
- トークンのタイプ(通常は
JWT
)と、署名に使用されるアルゴリズム(例:HS256
、RS256
)が含まれます。 - この情報はJSON形式で記述され、Base64URLエンコードされます。
- トークンのタイプ(通常は
-
ペイロード (Payload):
クレーム (claim)
と呼ばれる、実際のデータが含まれます。- ユーザーIDや有効期限、権限などの情報がJSON形式で記述されます。
- この情報もJSON形式で記述され、Base64URLエンコードされます。
- 注意点: ペイロードは誰でもデコードして内容を見ることができるため、パスワードなどの機密情報は含めてはいけません。
-
署名 (Signature):
- ヘッダーとペイロードをBase64URLエンコードした文字列を、秘密鍵とヘッダーで指定されたアルゴリズムで署名したものです。
- この署名があることで、トークンが改ざんされていないか、誰によって発行されたかを検証することができます。
JWT認証の仕組み
JWTは、主にWebアプリケーションやAPIの認証に利用されます。
- ログイン: ユーザーが認証情報(ID/パスワードなど)をサーバーに送信します。
- JWTの発行: サーバーは認証が成功すると、ユーザー情報を含むペイロードとヘッダー、秘密鍵を使ってJWTを生成し、クライアントに返します。
- トークンの利用: クライアントは受け取ったJWTを保存し、以降のAPIリクエストの際に、HTTPヘッダーなどにJWTを付与して送信します。
- 検証: サーバーはリクエストごとに、送られてきたJWTの署名を検証します。署名が正しければ、トークンが改ざんされておらず、信頼できるものであると判断し、ペイロード内の情報に基づいてユーザーを識別したり、アクセス権限を判断したりします。
JWTのメリット
- ステートレス: サーバー側でセッション情報を保持する必要がないため、スケーラビリティが高いです。サーバーはトークンの署名を検証するだけで済み、データベースなどに問い合わせる必要がありません。
- 軽量・汎用性: JSON形式でコンパクトに情報を格納できるため、HTTPヘッダーやURLパラメータなどでも扱いやすいです。異なるドメインやシステム間でも簡単に情報をやり取りできます。
- 改ざん検知: 署名によってトークンが改ざんされていないことを検証できるため、安全性が高いです。
- シングルサインオン (SSO): 複数のサービスで同じJWTを利用して認証を行う、SSOの仕組みに活用できます。
JWTで選べる署名にはどんなのがありますか?
JWT(JSON Web Token)の署名には、主に以下のようなアルゴリズムがあります。これらのアルゴリズムは、使用する鍵の種類によって大きく2つに分類できます。
1. 対称鍵アルゴリズム(HMAC)
- HS256 (HMAC using SHA-256)
- 特徴: 署名生成と検証に同じ「秘密鍵(シークレットキー)」を使用する方式です。
- メリット:
- 実装が比較的シンプルです。
- パフォーマンスが良いです。
- デメリット:
- 秘密鍵を、トークンを発行する側と検証する側の両方で共有する必要があります。
- そのため、秘密鍵の管理が厳重に求められ、特に複数のサービス間で鍵を共有する場合にセキュリティリスクが高まる可能性があります。
- 用途: 単一のアプリケーション内で、サーバーとクライアント間で認証を行う場合など、鍵の共有範囲が限定されている場合に適しています。
2. 非対称鍵アルゴリズム(RSA, ECDSA)
-
RS256 (RSA using SHA-256)
- 特徴: 署名生成に「秘密鍵」、検証に「公開鍵」を使用する方式です。公開鍵と秘密鍵はペアになっており、公開鍵から秘密鍵を特定することはできません。
- メリット:
- トークンを発行するサーバー(Auth0などの認証サービス)は秘密鍵を厳重に管理し、検証する側(APIサーバーなど)は公開鍵を公開することで、鍵の共有範囲を限定できます。
- 署名鍵を秘匿したまま、複数のサービスに公開鍵を配布して検証させることができ、よりセキュアな構成を構築できます。
- デメリット:
- 対称鍵方式に比べて計算コストが高く、パフォーマンスが劣る場合があります。
- 秘密鍵と公開鍵のペアを管理する手間が発生します。
- 用途: 複数のサービスやマイクロサービス間で認証を行う場合や、第三者にトークンの検証を委ねる場合(例: シングルサインオン)に広く推奨されます。
-
ES256 (ECDSA using P-256 and SHA-256)
- 特徴: 楕円曲線暗号(ECC)を利用した方式です。こちらも公開鍵と秘密鍵のペアを使用します。
- メリット:
- RS256と比べて、より小さな鍵サイズで同等のセキュリティ強度を達成できます。
- そのため、トークンサイズが小さくなり、パフォーマンスが向上します。特にリソースが限られた環境(モバイルデバイスなど)で有利です。
- デメリット:
- RS256に比べて比較的新しい技術であり、実装の複雑さや、一部の古い環境でのサポートが不十分な場合があります。
- 計算コストがHS256やRS256と比べて高くなる場合があります。
- 用途: 高いセキュリティ強度とパフォーマンスの両方が求められる場合に選択されます。
アルゴリズムの選択について
一般的に、JWTの署名アルゴリズムは、以下の観点から選択されます。
- HS256: 鍵の管理がシンプルで、単一のサービス内で完結する認証システムに適しています。
- RS256: 複数のサービス間で認証を共有する場合に最も広く推奨されるアルゴリズムです。認証サーバーは秘密鍵を保持し、リソースサーバーは公開鍵で検証することで、安全性が高まります。
- ES256: RS256よりもさらに高いパフォーマンスや、よりコンパクトなトークンが求められる場合に有効な選択肢です。
多くの認証サービスやライブラリでは、これらのアルゴリズムがサポートされており、特にHS256
とRS256
は広く普及しています。セキュリティと利便性のバランスを考慮して、自身のシステム構成に最適なアルゴリズムを選択することが重要です。
類似の規格で暗号化も行えるとか?
はい、JWTと類似の規格で、暗号化も行えるものがあります。それが JWE(JSON Web Encryption) です。
JWTは主に署名によって改ざんされていないことを保証しますが、ペイロードの内容自体はBase64URLエンコードされているだけで、誰でもデコードして見ることができます。このため、機密情報を含めることは推奨されません。
一方、JWEは、JWTと同じJSONベースの規格ですが、暗号化を目的としています。これにより、トークンの内容を第三者から隠すことができます。
JWTとJWEの関係性
JWT、JWE、そしてそれらをまとめるための仕様群は、JOSE(JSON Object Signing and Encryption) と呼ばれるフレームワークの一部です。JOSEは、JSON形式のデータを安全にやり取りするための共通規格を定めています。
規格名 | 役割 | 主な目的 |
---|---|---|
JWT (JSON Web Token) | トークンの構造を定義する | 情報をコンパクトに表現 |
JWS (JSON Web Signature) | 署名の仕組みを定義する | データの改ざん防止、発行者の証明 |
JWE (JSON Web Encryption) | 暗号化の仕組みを定義する | データの機密性保護 |
一般的に「JWT」という言葉は、署名されたトークンである「JWS」のことを指す場合が多いです。しかし、厳密には「JWT」はトークンの形式を定義するものであり、そのトークンに署名を行うのがJWS、暗号化を行うのがJWEという関係になります。
JWEの仕組み
JWEトークンは、JWTと同様にピリオド(.
)で区切られたいくつかの要素から構成されますが、その内容は異なります。
- JWEヘッダー: 使用する暗号化アルゴリズムや、コンテンツの暗号化に使用する鍵の暗号化アルゴリズムなどが含まれます。
- JWE暗号化キー: コンテンツの暗号化に使われる共通鍵(CEK)を、受信者の公開鍵などで暗号化したものです。
- 初期化ベクトル: 暗号化に必要な情報です。
- 暗号化されたデータ: 実際のペイロード(クレーム)を暗号化したものです。
- 認証タグ: データが改ざんされていないかを検証するためのタグです。
JWEの利用例
- 機密情報を含むトークン: ユーザーの個人情報や、機密性の高い権限情報などをトークンに含めたい場合に利用されます。
- 特定の受信者のみが内容を解読できるトークン: 公開鍵暗号方式を利用することで、特定の受信者だけがトークンを復号できるようにすることができます。
このように、JWTとJWEは異なる目的を持つ規格であり、用途に応じて使い分けられます。
- JWT(JWS): データの改ざんがないことを保証し、公開しても問題ない情報をやり取りする場合
- JWE: データの機密性を確保し、第三者に見られたくない情報をやり取りする場合
HTTPSに代表される様な証明書ベースの署名?も作れますか?
はい、HTTPSで使われるような証明書ベースの署名も、JWTで利用することができます。これは、一般的にX.509証明書と組み合わせて、JWTの署名を行う方法です。
X.509証明書とは
HTTPSで使われるSSL/TLS通信では、サーバーの身元を証明するためにX.509証明書が利用されます。この証明書は、信頼できる第三者機関(認証局、CA)によって署名されており、以下の情報が含まれています。
- 証明書の所有者情報(ドメイン名、組織名など)
- 公開鍵
- 証明書の有効期限
- 証明書を発行した認証局の情報
これにより、クライアントは認証局の公開鍵を使って証明書の署名を検証し、サーバーが本当にそのドメインの所有者であることを信頼できるようになります。
JWTとX.509証明書の連携
JWTは、RS256
やES256
のような非対称鍵アルゴリズムを使って署名されることがよくあります。この場合、JWTを発行する側が秘密鍵を使い、検証する側が公開鍵を使います。
X.509証明書には公開鍵が含まれているため、この公開鍵をJWTの検証に利用することができます。
JWTのヘッダーには、署名アルゴリズムを指定するalg
クレームの他に、証明書に関する情報を指定するための特別なクレーム(パラメータ)がいくつかあります。
x5u
(X.509 URL): JWTの署名に使用された証明書、または証明書チェーン全体が格納されているURL。x5c
(X.509 Certificate Chain): 署名に使用された証明書チェーン自体を直接格納します。通常は、エンコードされた証明書の配列として表現されます。x5t
(X.509 Certificate SHA-1 Thumbprint): 署名に使用された証明書のSHA-1ハッシュ値。x5t#S256
(X.509 Certificate SHA-256 Thumbprint): 署名に使用された証明書のSHA-256ハッシュ値。
仕組みの例
-
JWTの発行:
- サーバーは、自身の秘密鍵を使ってJWTに署名します。
- このとき、JWTのヘッダーに
x5c
クレームを追加し、サーバーのX.509証明書チェーンを埋め込みます。
-
JWTの検証:
- クライアントはJWTを受け取ります。
- まず、ヘッダーから
x5c
クレームを読み取り、証明書チェーンを取得します。 - この証明書チェーンを信頼できる認証局の証明書までたどり、証明書が有効であることを検証します。
- 証明書から公開鍵を抽出します。
- 抽出した公開鍵を使って、JWTの署名を検証します。
メリットと注意点
メリット
- 信頼性の向上: JWTの署名を、公開鍵基盤(PKI)によって保証された証明書と結びつけることで、JWTの信頼性をさらに高めることができます。
- 鍵管理の簡素化: 公開鍵そのものを直接配布するのではなく、公開された証明書から鍵を取得できるため、鍵の管理が体系化されます。
注意点
- 証明書の検証: クライアントは、JWTの署名検証に加えて、証明書自体の有効性(有効期限、失効状況など)を検証する責任があります。これを怠ると、セキュリティ上の脆弱性につながる可能性があります。
- パフォーマンス: 証明書チェーンの検証は、単純な公開鍵の検証よりも複雑であり、オーバーヘッドが発生する可能性があります。
このように、JWTはHTTPSで使われる証明書と同じ公開鍵基盤(PKI)の仕組みと組み合わせて利用することができ、より厳格な認証やセキュリティが求められる場面で活用されています。