このトピックでは、JWT(JSON Web Token)と JWS(JSON Web Signature)に関する一般情報と、Apigee プロキシのデベロッパーにとって関心のありそうな Apigee JWS / JWT のポリシーを紹介します。
はじめに
JWS と JWT の両方が一般的に、接続されているアプリケーションの間でクレームやアサーションを共有するために使用されます。JWS / JWT ポリシーによって Edge API プロキシは以下のことが可能になります。
- 署名付きの JWT または JWS を生成する。
- 署名付きの JWT または JWS と JWS / JWT 内のクレームを確認する。
- 署名を検証することなく、署名付きの JWT または JWS をデコードする。
2 番目と 3 番目のケースでは、ポリシーは、追加のポリシーを許可する変数、あるいはバックエンド サービス自体も設定し、検証されたクレームを検査して、これらのクレームに基づいて決定を行います。
Verify JWS / JWT ポリシーを使用しているとき、無効な JWS / JWT は拒否されてエラー状態になります。同様に、Decode JWS / JWT ポリシーを使用しているとき、不正な形式の JWS / JWT はエラー状態になります。
動画
JWT の概要についての短い動画をご覧ください。この動画は JWT の生成用ですが、コンセプトの多くは JWS と同じです。
JWT 構造の詳細を学習するための短い動画をご覧ください。
使用例
JWS / JWT ポリシーを使用して、次のことが可能です。
- 新しい JWS / JWT を、Edge プロキシのプロキシ側、あるいはターゲット エンドポイント側に生成します。たとえば、JWS / JWT を生成してクライアントに返すプロキシ リクエスト フローを作成できます。あるいは、ターゲット リクエスト フローで JWS / JWT を生成し、それをターゲットに送信されるリクエストに添付するようプロキシを設計できます。その後、これらのクレームを、バックエンド サービスがさらなるセキュリティ処理を適用するために使用できるようになります。
- 受信クライアント リクエスト、ターゲット サービス レスポンス、Service Callout ポリシー レスポンスなどのソースから取得した JWS / JWT を検証し、クレームを抽出します。Edge は JWS / JWT の署名を検証し、それがサードパーティによって生成された JWS / JWT なのか、Edge 自体が生成した JWS / JWT なのかを、RSA アルゴリズムか HMAC アルゴリズムを使用して調べます。
- JWS / JWT をデコードします。デコードは、JWS / JWT を検証する前に、JWS / JWT 内からのクレームの値(JWT)またはヘッダーの値(JWS / JWT)を知っておく必要がある場合に、Verify JWS / JWT ポリシーとともに使用すると最も役立ちます。
JWS / JWT の各部
署名された JWS / JWT は情報を 3 つの部分(ヘッダー、ペイロード、署名)にエンコードします。
header.payload.signature
- Generate JWS / JWT ポリシーは、3 つの部分をすべて作成します。
- Verify JWS / JWT ポリシーは 3 つの部分をすべて調べます。
- Decode JWS / JWT ポリシーは、ヘッダーとペイロードを調べます。
JWS では、JWS のペイロードが省略される分離形式もサポートされます。
header..signature
分離済み JWS では、ペイロードが個別に JWS から送信されます。Verify JWS ポリシーの <DetachedContent>
要素を使用して、RAW で未エンコードの JWS ペイロードを指定します。次に、Verify JWS ポリシーで、JWS のヘッダーと署名、<DetachedContent>
要素で指定されたペイロードを使用して、JWS を検証します。
トークンおよびそのエンコード方法と署名方法の詳細については、以下をご覧ください。
- JWT: IETF RFC7519
- JWS: IETF RFC7515
JWS と JWT の違い
JWT または JWS を使用して、接続されているアプリケーションの間でクレームやアサーションを共有できます。この 2 つの主な違いは、ペイロードの表現です。
- JWT
- ペイロードは常に JSON オブジェクト
- ペイロードは常に JWT に接続される
- トークンの
typ
ヘッダーが常にJWT
に設定される
- JWS
- ペイロードは、JSON オブジェクト、バイト ストリーム、オクテット ストリームなど、あらゆる形式で表現できる
- ペイロードを JWS に接続する必要はない
JWT 形式では常に JSON オブジェクトを使用してペイロードを表現するため、Edge Generate JWT ポリシーと Verify JWT ポリシーには、aud、iss、sub などの共通の Registered Claim Names を処理するための組み込みサポートがあります。つまり、Generate JWT ポリシーの要素を使用して、ペイロードにこうしたクレームを設定したり、Verify JWT ポリシーの要素を使用してこうした値を検証したりできます。詳しくは、JWT の仕様の Registered Claim Names セクションをご覧ください。
特定の Registered Claim Names のサポートとともに、Generate JWT ポリシーでは任意の名前のクレームを JWT に追加することが直接サポートされます。各クレームは単純な名前と値のペアで、値のタイプは数値、ブール値、文字列、マップ、配列にできます。
JWS ではペイロードに任意のデータ表現を使用できるため、クレームをペイロードに追加することはできません。Generate JWS ポリシーでは、任意の名前のクレームを JWS のヘッダーに追加することがサポートされます。また、JWS ポリシーでは、JWS でペイロードが省略される分離ペイロードもサポートされます。分離ペイロードを使用すると、JWS とペイロードを個別に送信できます。これは、いくつかのセキュリティ基準で要求されています。
署名アルゴリズムについて
JWS / JWT Verification ポリシーと JWS / JWT Generation ポリシーは、RSA、RSASSA-PSS、ECDSA、HMAC のアルゴリズムをサポートし、ビット強度 256、384、または 512 の SHA2 チェックサムを使用します。JWS / JWT Decode ポリシーは、JWS / JWT を署名するために使用したアルゴリズムに関係なく動作します。
HMAC アルゴリズム
HMAC アルゴリズムでは、署名を作成する(JWS / JWT に署名するとも言います)ためと、署名を検証するために、共有シークレット(秘密鍵)を使用します。
秘密鍵の最小長は、アルゴリズムのビット強度に応じて異なります。
- HS256: 鍵の最小長が 32 バイト
- HS386: 鍵の最小長が 48 バイト
- HS512: 鍵の最小長が 64 バイト
RSA アルゴリズム
RSA アルゴリズムでは、暗号署名で公開鍵 / 秘密鍵のペアを使用します。RSA 署名では、署名する側は RSA 秘密鍵を使用して JWS / JWT に署名し、検証する側は一致する RSA 公開鍵を使用して JWS / JWT の署名を検証します。鍵のサイズ要件はありません。
RSASSA-PSS アルゴリズム
RSASSA-PSS アルゴリズムは、RSA アルゴリズムを更新したものです。RSS と同様に、RSASSA-PSS では、暗号署名で RSA 公開鍵 / 秘密鍵のペアを使用します。鍵の形式は RSS と同じです。署名する側は秘密鍵を使用して JWS / JWT に署名し、検証する側は一致する公開鍵を使用して JWS / JWT の署名を検証します。鍵のサイズ要件はありません。
ECDSA アルゴリズム
Elliptic Curve Digital Signature Algorithm(ECDSA)アルゴリズムは、P-256 曲線、P-384 曲線、P-521 曲線がある楕円曲線暗号アルゴリズムです。ECDSA アルゴリズムを使用する場合、指定する必要がある公開鍵と秘密鍵のタイプが特定されます。
アルゴリズム | 曲線 | 鍵の要件 |
---|---|---|
ES256 | P-256 | P-256 曲線(secp256r1 や prime256v1 とも呼ばれる)から生成される鍵 |
ES384 | P-384 | P-384 曲線(secp384r1 とも呼ばれる)から生成される鍵 |
ES512 | P-521 | P-521 曲線(secp521r1 とも呼ばれる)から生成される鍵 |
鍵による暗号化アルゴリズム
JWS / JWT ポリシーでは、OpenSSL によってサポートされるすべての鍵による暗号化アルゴリズムがサポートされます。
JSON Web Key Set(JWKS)を使用した JWS / JWT の検証
署名した JWS / JWT を検証するときは、トークンを署名するために使用した秘密鍵に関連付けられた公開鍵を指定する必要があります。JWS / JWT ポリシーを検証するために公開鍵を指定するには、2 つの方法があります。
- 実際の公開鍵の値(通常はフロー変数で指定)を使用する
- JWKS でラップされた公開鍵を使用する
JWKS について
JWKS は、JSON Web Key(JWK)のセットを表す JSON 構造です。JWK は、暗号鍵を表す JSON データ構造です。JWK と JWKS については、RFC7517 で説明されています。Appendix A. Example JSON Web Key Sets の JKWS の例をご覧ください。
JWKS 構造
RFC7517 では、「RSA」や「EC」などの各鍵タイプの JWKS 鍵要素が説明されています。たとえば、鍵のタイプに応じて、パラメータに以下が含まれます。
- kty - 「RSA」、「EC」などの鍵タイプ。
- kid(鍵 ID) - 任意の値にできます(鍵セット内で重複しないこと)。受信 JWT が有する鍵 ID が JWKS のセットに存在する場合、ポリシーは正しい公開鍵を使用して JWS / JWT 署名を検証します。
以下は、省略可能な要素とそれぞれの値です。
- alg - 鍵アルゴリズム。JWS / JWT の署名アルゴリズムと一致している必要があります。
- use - 存在する場合は、sig にする必要があります。
以下の JWKS には必須の要素と値が含まれており、Edge(https://www.googleapis.com/oauth2/v3/certs)で有効となります。
{ "keys":[ { "kty":"RSA", "alg":"RS256", "use":"sig", "kid":"ca04df587b5a7cead80abee9ea8dcf7586a78e01", "n":"iXn-WmrwLLBa-QDiToBozpu4Y4ThKdwORWFXQa9I75pKOvPUjUjE2Bk05TUSt7-V7KDjCq0_Nkd-X9rMRV5LKgCa0_F8YgI30QS3bUm9orFryrdOc65PUIVFVxIwMZuGDY1hj6HEJVWIr0CZdcgNIll06BasclckkUK4O-Eh7MaQrqb646ghFlG3zlgk9b2duHbDOq3s39ICPinRQWC6NqTYfqg7E8GN_NLY9srUCc_MswuUfMJ2cKT6edrhLuIwIj_74YGkpOwilr2VswKsvJ7dcoiJxheKYvKDKtZFkbKrWETTJSGX2Xeh0DFB0lqbKLVvqkM2lFU2Qx1OgtTnrw", "e":"AQAB" }, { "kty":"EC", "alg":"ES256", "use":"enc", "kid":"k05TUSt7-V7KDjCq0_N" "crv":"P-256", "x":"Xej56MungXuFZwmk_xccvsMpCtXmqhvEEMCmHyAmKF0", "y":"Bozpu4Y4ThKdwORWFXQa9I75pKOvPUjUjE2Bk05TUSt", } ] }
JWKS を使用するようにプロキシを設計する
JWS / JWT を発行元から取得するとき、一般に発行元は鍵 ID(kid)を JWS / JWT ヘッダーに挿入します。この鍵によって、JWS / JWT の受信者は、署名した JWS / JWT の署名を検証するために必要な公開鍵または秘密鍵を見つける方法がわかります。
例として、発行元が JWT に秘密鍵を使って署名するとしましょう。「鍵 ID」は、JWT を検証するために使用するのに適合する公開鍵を特定します。公開鍵のリストは、通常はよく知られているエンドポイント(たとえば https://www.googleapis.com/oauth2/v3/certs)にあります。
以下は、Edge(または JWKS と連携するあらゆるプラットフォーム)が JWKS を持っている JWS / JWT と連携するために実行する必要がある、基本的なシーケンスです。
- JWS / JWT ヘッダーを調べて鍵 ID(kid)を見つけます。
- JWS / JWT ヘッダーを調べて、RS256 などの署名アルゴリズム(alg)を見つけます。
- 鍵と ID のリストを、指定の発行元のよく知られたエンドポイントの JWKS から取り出します。
- JWS / JWT ヘッダーに記載された鍵 ID(と、JWKS 鍵でアルゴリズムが指定されている場合は、一致するアルゴリズム)を使用し、鍵のリストから公開鍵を抽出します。
- この公開鍵を使って、JWS / JWT の署名を検証します。
Edge API プロキシ デベロッパーは、JWS / JWT 検証を実行するために以下を行う必要があります。
- 鍵と ID のリストを、指定の発行元の周知のエンドポイントから取り出します。この手順で Service Callout ポリシーを使用できます。
- Verify JWS / JWT ポリシーで、
<Source>
要素の JWS / JWT の場所と、<PublicKey/JWKS>
要素の JWKS ペイロードを指定します。たとえば、VerifyJWT ポリシーの場合:<VerifyJWT name="JWT-Verify-RS256"> <Algorithm>RS256</Algorithm> <Source>json.jwt</Source> <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables> <PublicKey> <JWKS ref="public.jwks"/> </PublicKey> <Subject>apigee-seattle-hatrack-montage</Subject> <Issuer>urn://apigee-edge-JWT-policy-test</Issuer> <Audience>urn://c60511c0-12a2-473c-80fd-42528eb65a6a</Audience> <AdditionalClaims> <Claim name="show">And now for something completely different.</Claim> </AdditionalClaims> </VerifyJWT>
Verify JWT ポリシーがその他すべての操作を行います。
- JWT でアサートされた鍵 ID(kid)に一致する鍵 ID を持つ鍵が JWKS に見つからない場合、Verify JWT ポリシーはエラーを返し、JWT を検証しません。
- 受信 JWT がヘッダー内に鍵 ID(kid)を持たない場合、この keyid-to-verification-key のマッピングは不可能です。
プロキシ設計者は、使用する鍵を決定する責任があります(場合によっては、これは固定のハードコード形式の鍵となります)。