コンテンツにスキップ

JWT検証の設定

Cloudflare APIを使用してJWT検証を設定します。これにはトークン設定とトークン検証ルールが必要です。

トークン設定

トークン設定は、クライアントから送信されたJSON Webトークン(JWT)を検証するために使用されるJSON Webキーセット(JWKs)を定義し、これらのJWTがリクエスト内でどこに送信されるかに関する情報を提供します。

トークン設定には以下の情報が必要です:

フィールド名
説明注釈
title設定の目的を迅速に特定できる人間が読める名前です。本番JWT設定50文字以内に制限されています。
description titleよりも詳細な人間が読める説明で、顧客が設定の使用をより良く文書化できる手段として機能します。この設定はエンドポイント管理のすべてのエンドポイントで使用され、認証ヘッダー内のJWTをチェックします。500文字以内に制限されています。
token_sourcesJWTがリクエスト内で見つかる可能性のある場所のリストです。http.request.headers[\"authorization\"][0]
http.request.cookies[\"Authorization\"][0]
以下の情報を参照してください。
token_type検証するトークンのタイプを指定します。jwt現在サポートされているのはjwtのみです。
credentialsJWTを検証するために使用されるべき暗号化された公開鍵を説明します。このフィールドはJSONウェブキーでなければなりません。以下の例を参照してください。以下の情報を参照してください。

トークンソース

各項目は、文字列に解決されるルールセットエンジンの式でなければなりません。

現在サポートされているフィールドはhttp.request.headershttp.request.cookiesです。

最大4つのトークンソースを設定できます。リクエストにこれらのフィールドが複数設定されている場合、1つだけが使用されます。リクエストトークン内の先頭のBearer: 文字列は自動的に無視されます。

ルールセットエンジンフィールドの操作に関する詳細は、ルールセットエンジンのドキュメントを参照してください。

認証情報

API Shieldは、RS256RS384RS512PS256PS384PS512ES256、およびES384タイプの認証情報をサポートしています。RSAキーは少なくとも2048ビットでなければなりません。各JSONウェブキーには「KID」が必要で、JWTのヘッダーにも存在する必要があります。これにより、API Shieldがそれらを一致させることができます。

キーのロールオーバーを支援するために、最大4つの異なるキーを許可します。

Cloudflareは、各キーから不要なフィールドを削除し、サポートされていないキーを削除します。

API呼び出しの出力を検証して、結果のキーが意図した通りに表示されることを確認することを強くお勧めします。

トークン設定JSONオブジェクト

以下の例は、Cloudflare APIを使用してトークン設定を作成するために必要なすべての情報を含むJSONオブジェクトを示しています。テスト用のJWKを作成したい場合は、mkjwk JSON Web Key Generatorを参照してください。

{
"title": "本番JWT設定",
"description": "この設定は認証ヘッダーまたはクッキー内のJWTをチェックします。",
"token_sources": [
"http.request.headers[\"authorization\"][0]",
"http.request.cookies[\"Authorization\"][0]"
],
"token_type": "jwt",
"credentials": {
"keys": [
{
"kty": "EC",
"use": "sig",
"crv": "P-256",
"kid": "93UrzmNu1mqXs5cZcvCPkTlMHB2Jya30vSTkiBb0vhU",
"x": "QG3VFVwUX4IatQvBy7sqBvvmticCZ-eX5-nbtGKBOfI",
"y": "A3PXCshn7XcG7Ivvd2K_DerW4LHAlIVKdqhrUnczTD0",
"alg": "ES256"
}
]
}
}

Cloudflare APIを使用してトークン設定を作成する

cURLまたは他のAPIクライアントツールを使用して、新しい設定をCloudflareのAPIに送信してJWT検証を有効にします。{zone_id}を関連するゾーンIDに置き換え、認証情報ヘッダーを追加してください。

cURLを使用した例
curl "https://api.cloudflare.com/client/v4/zones/{zone_id}/api_gateway/token_validation" \
--header 'Content-Type: application/json' \
--data '{
"title": "本番JWT設定",
"description": "この設定は認証ヘッダーまたはクッキー内のJWTをチェックします。",
"token_sources": [
"http.request.headers[\"authorization\"][0]",
"http.request.cookies[\"Authorization\"][0]"
],
"token_type": "jwt",
"credentials": {
"keys": [
{
"kty": "EC",
"use": "sig",
"crv": "P-256",
"kid": "93UrzmNu1mqXs5cZcvCPkTlMHB2Jya30vSTkiBb0vhU",
"x": "QG3VFVwUX4IatQvBy7sqBvvmticCZ-eX5-nbtGKBOfI",
"y": "A3PXCshn7XcG7Ivvd2K_DerW4LHAlIVKdqhrUnczTD0",
"alg": "ES256"
}
]
}
}'

レスポンスはCloudflareのv4レスポンスエンベロープ内にあり、結果には作成された設定が含まれます。返されたIDに注意してください。これは、APIを使用してトークン検証ルールを作成する際にトークン設定を参照するために使用されます。

例のレスポンス
{
"result": {
"id": "d5902294-00c3-4aed-b517-57e752e9cd58",
"token_type": "JWT",
"title": "本番JWT設定",
"description": "この設定は認証ヘッダーまたはクッキー内のJWTをチェックします。",
"token_sources": [
"http.request.headers[\"authorization\"][0]",
"http.request.cookies[\"Authorization\"][0]"
],
"credentials": {
"keys": [
{
"x": "QG3VFVwUX4IatQvBy7sqBvvmticCZ-eX5-nbtGKBOfI",
"y": "A3PXCshn7XcG7Ivvd2K_DerW4LHAlIVKdqhrUnczTD0",
"alg": "ES256",
"crv": "P-256",
"kid": "93UrzmNu1mqXs5cZcvCPkTlMHB2Jya30vSTkiBb0vhU",
"kty": "EC"
}
]
},
"created_at": "2023-11-08T16:45:17.236841Z",
"last_updated": "2023-11-08T16:45:17.236841Z"
},
"success": true,
"errors": [],
"messages": []
}

トークン検証ルール

トークン検証ルールを使用すると、既存のトークン設定を使用してセキュリティポリシーを強制できます。

トークン検証ルールは、Cloudflare APIまたはダッシュボードを使用して構成できます。

フィールド名
説明注釈
title迅速に特定できる人間が読める名前です。v1およびv2.example.comでのJWT検証50文字以内に制限されています。
descriptiontitleよりも詳細な人間が読める説明で、文書化を助けます。有効なauthorizationヘッダーのないリクエストをログに記録します。500文字以内に制限されています。
actionexpressionを満たさないリクエストに対して取られるファイアウォールアクション。log可能な値: logまたはblock
enabledルールを有効または無効にします。true可能な値: trueまたはfalse
expressionルールのセキュリティポリシー。is_jwt_valid ("00170473-ec24-410e-968a-9905cf0a7d03")Cloudflare APIを使用してルールを作成する際は、引用符をエスケープしてください。
詳細はセキュリティポリシーの定義を参照してください。
selectorこのルールでカバーされる操作を構成します。操作にルールを適用するを参照してください。

セレクター

セレクターは、トークン検証ルールの範囲を制御します。

特定のホスト名やドメインのサブドメインでのみJWT検証が必要な場合は、セレクターにホスト名を使用してJWT検証ルールに含めます。

設計上、常に有効なJWTが使用されないエンドポイント(最初に有効なJWTを確立するために使用されるパスとメソッドなど)をJWT検証から除外する必要がある場合は、エンドポイントの操作IDを使用してセレクターで除外する必要があります。

操作IDを見つけるには、エンドポイント管理を参照するか、Cloudflare APIを使用してください。

セキュリティポリシーの定義

トークン検証ルールの式は、リクエストが満たす必要があるセキュリティポリシーを定義します。

たとえば、式is_jwt_valid("51231d16-01f1-48e3-93f8-91c99e81288e") or is_jwt_valid("51231d16-01f1-48e3-93f8-91c99e81288e")は、受信リクエストに少なくとも1つの有効な認証トークンがない場合にトリガーされます。

これらの式は、ルールセットエンジンで使用される式に似ていますが、いくつかの重要な違いがあります:

  • トークン検証ルールのアクションは、式がfalseと評価される場合にトリガーされます。これは、ルールセット式とは異なります。
  • トークン検証ルールは、トークン設定を参照する専用の関数を使用できます。

orandeqなどの演算子は、ルールセットエンジンで使用される式と同様に、式内で使用できます。

リクエスト上のJWTトークンと対話するために使用できる関数は以下の通りです:

機能
説明ノート
is_jwt_valid(token_configuration_id String) booltoken_configuration_idのIDを持つトークン設定に従ってリクエストが有効なトークンを持っている場合はTrueを返します。token_configuration_idは既存のトークン設定のIDでなければなりません。このトークンがリクエストに存在しない場合はfalseを返します。
is_jwt_present(token_configuration_id String) booltoken_configuration_idのIDを持つトークン設定に従ってリクエストがトークンを持っている場合はTrueを返します。token_configuration_idは既存のトークン設定のIDでなければなりません。

一般的な使用例

どのセキュリティポリシーを使用するかを理解するために、以下の例を参照してください。ほとんどの使用例では、CloudflareはAPI全体で有効なトークンを要求し、トークンを確立または更新するために使用されるパスを除外することを推奨します。

トークンを要求する

is_jwt_present("51231d16-01f1-48e3-93f8-91c99e81288e")の式は、リクエストにJWTが欠けている場合にアクションをトリガーします。

これは、認証ヘッダーが欠けているリクエストをログに記録するために、トークン検証ルールのlogアクションと組み合わせることができます。

有効なトークンを要求する

is_jwt_valid("51231d16-01f1-48e3-93f8-91c99e81288e")の式は、リクエストに有効なJWTがない場合にアクションをトリガーします。

これは、無効な資格情報またはトークンがないリクエストをブロックするために、トークン検証ルールのblockアクションと組み合わせることができます。

2つの可能なトークンのうち少なくとも1つを要求する

is_jwt_valid("51231d16-01f1-48e3-93f8-91c99e81288e") or is_jwt_valid("fddfc39e-3686-4683-ab23-bf917da6bb43")の式は、リクエストに少なくとも1つの有効なトークンがない場合にアクションをトリガーします。

これは、JWKを複数のトークン設定に分割する必要がある場合に発生する可能性があります。

有効なトークンを要求するが、トークンのないリクエストは無視する

is_jwt_valid("51231d16-01f1-48e3-93f8-91c99e81288e") or not is_jwt_valid("51231d16-01f1-48e3-93f8-91c99e81288e")の式は、リクエストに無効なトークンがある場合にアクションをトリガーし、トークンが全くないリクエストは無視します。

操作にルールを適用する

1つのトークン検証ルールのみが操作に適用できます。操作が複数のルールに該当する場合、最も優先度の高いルールが適用されます。

selectorフィールドを使用して、JWT検証が強制される操作を構成できます。

例えば、以下のセレクターは、v1.example.comおよびv2.example.comのすべての操作にルールを適用しますが、これらのホスト上の2つの操作は除外されます:

セレクターの例
{
"include": [
{
"host": [
"v1.example.com",
"v2.example.com"
]
}
],
"exclude": [
{
"operation_ids": [
"f9c5615e-fe15-48ce-bec6-cfc1946f1bec", // POST v1.example.com/login
"56828eae-035a-4396-ba07-51c66d680a04" // POST v2.example.com/login
]
}
]
}

操作はホストレベルで含めることができ、操作ごとに無視することができます。

このルールでカバーされる操作を確認するには、POST /zones/{zone_id}/api_gateway/token_validation/rules/previewエンドポイントを使用できます:

cURLを使用した例
curl --request PUT \
'https://api.cloudflare.com/client/v4/zones/{zone_id}/api_gateway/token_validation/rules/preview' \
--header 'Content-Type: application/json' \
--data '{
"include": [
{
"host": [
"v1.example.com",
"v2.example.com"
]
}
],
"exclude": [
{
"operation_ids": [
"f9c5615e-fe15-48ce-bec6-cfc1946f1bec", // POST v1.example.com/login
"56828eae-035a-4396-ba07-51c66d680a04" // POST v2.example.com/login
]
}
]
}'

レスポンスには、追加のstateフィールドを持つすべての操作が含まれます。

stateフィールドはignoredexcluded、またはincludedのいずれかです。含まれる操作は、指定したホスト名セレクターに一致します。除外された操作は、セレクターで指定した操作IDに一致します。無視された操作は、セレクターで指定されたものに一致しない操作です。

結果
{
"result": {
"operations": [
{
"operation_id": "ed15fcb6-5a73-41cd-91af-8c61e5bb1cdb",
"method": "GET",
"host": "example.com",
"endpoint": "/api/accounts/{var1}",
"last_updated": "2023-05-24T14:54:34.806506Z",
"state": "ignored"
},
{
"operation_id": "e7a582cd-3cfb-4061-ab5b-722e6e42f545",
"method": "GET",
"host": "v1.example.com",
"endpoint": "/api/accounts/{var1}",
"last_updated": "2023-05-24T14:54:34.806506Z",
"state": "included"
},
{
"operation_id": "ddd5df5a-795c-40ce-b38c-38e9d7ef9ae8",
"method": "GET",
"host": "v2.example.com",
"endpoint": "/api/accounts/{var1}",
"last_updated": "2023-05-24T14:54:34.806506Z",
"state": "included"
},
{
"operation_id": "4d20befb-0120-45d5-9b29-5835fd41b44e",
"method": "GET",
"host": "v3.example.com",
"endpoint": "/api/accounts/{var1}",
"last_updated": "2023-05-24T14:54:34.806506Z",
"state": "ignored"
},
{
"operation_id": "f9c5615e-fe15-48ce-bec6-cfc1946f1bec",
"method": "POST",
"host": "v1.example.com",
"endpoint": "/login",
"last_updated": "2023-05-24T14:54:34.806506Z",
"state": "excluded"
},
{
"operation_id": "56828eae-035a-4396-ba07-51c66d680a04",
"method": "POST",
"host": "v2.example.com",
"endpoint": "/login",
"last_updated": "2023-05-24T14:54:34.806506Z",
"state": "excluded"
},
{
"operation_id": "cf86874c-8d0c-4337-ae14-4e2459b541ac",
"method": "GET",
"host": "v3.example.com",
"endpoint": "login",
"last_updated": "2023-05-24T14:54:34.806506Z",
"state": "ignored"
}
],
"total": 7,
"included": 2,
"excluded": 2,
"ignored": 3,
"selected_hosts": [
"v1.example.com",
"v2.example.com"
],
"available_hosts": [
"example.com",
"v1.example.com",
"v1.example.com",
"v3.example.com"
]
},
"success": true,
"errors": [],
"messages": [],
"result_info": {
"page": 1,
"per_page": 20,
"count": 20,
"total_count": 1631
}
}

included状態の操作は、トークン検証ルールの対象となります。レスポンスには、result.selected_hostsに含まれる操作のホスト名と、result.available_hostsにすべてのゾーン操作で使用されるホスト名が表示されます。

リクエストボディに空のオブジェクトを送信することもできます:

cURLを使用した例
curl --request PUT \
'https://api.cloudflare.com/client/v4/zones/{zone_id}/api_gateway/token_validation/rules/preview' \
--header 'Content-Type: application/json' \
--data '{ }'

レスポンスには、すべてのゾーン操作とすべての可能なホストが表示され、独自のセレクターを構築するために使用できます。

トークン検証ルールのJSONオブジェクト

以下の例は、Cloudflare APIを使用してトークン検証ルールを作成するために必要なすべての情報を含むJSONオブジェクトを示しています。

トークン設定IDや操作IDは、ゾーンに存在するIDに置き換えてください。

トークン検証ルールのJSON例
[
{
"title": "v1およびv2.example.comでのJWT検証",
"description": "有効な認証ヘッダーがないリクエストをログに記録します。",
"action": "log",
"enabled": true,
"expression": "is_jwt_valid(\"00170473-ec24-410e-968a-9905cf0a7d03\")",
"selector": {
"include": [
{
"host": [
"v1.example.com",
"v2.example.com"
]
}
],
"exclude": [
{
"operation_ids": [
"f9c5615e-fe15-48ce-bec6-cfc1946f1bec",
"56828eae-035a-4396-ba07-51c66d680a04"
]
}
]
}
}
]

Cloudflare APIを使用してトークン検証ルールを作成する

cURLまたは他のAPIクライアントツールを使用して、新しい構成をCloudflareのAPIに送信してJWT検証を有効にします。{zone_id}を関連するゾーンIDに置き換え、認証資格情報ヘッダーを追加してください。

トークン設定IDや操作IDは、ゾーンに存在するIDに置き換えてください。

1つのリクエストで複数のルールを作成できます。その場合、リクエストボディのJSON配列に複数のルールオブジェクトを渡します。

cURLを使用した例
curl "https://api.cloudflare.com/client/v4/zones/{zone_id}/api_gateway/token_validation/rules" \
--header 'Content-Type: application/json' \
--data '[
{
"title": "v1およびv2.example.comでのJWT検証",
"description": "有効な認証ヘッダーがないリクエストをログに記録します。",
"action": "log",
"enabled": true,
"expression": "is_jwt_valid(\"00170473-ec24-410e-968a-9905cf0a7d03\")",
"selector": {
"include": [
{
"host": [
"v1.example.com",
"v2.example.com"
]
}
],
"exclude": [
{
"operation_ids": [
"f9c5615e-fe15-48ce-bec6-cfc1946f1bec",
"56828eae-035a-4396-ba07-51c66d680a04"
]
}
]
}
}
]'

レスポンスはCloudflareのv4レスポンスエンベロープ内にあり、結果には作成されたルールが含まれます。各ルールの返されたIDに注意してください。これは、既存のルールを編集または削除するために使用できます。

結果
{
"result": [
{
"id": "5ec7c417-6964-4b24-b82c-a23a7ec8f90c",
"title": "v1およびv2.example.comでのJWT検証",
"description": "有効な認証ヘッダーがないリクエストをログに記録します。",
"action": "log",
"enabled": true,
"expression": "is_jwt_valid(\"00170473-ec24-410e-968a-9905cf0a7d03\")",
"selector": {
"include": [
{
"host": [
"v1.example.com",
"v2.example.com"
]
}
],
"exclude": [
{
"operation_ids": [
"f9c5615e-fe15-48ce-bec6-cfc1946f1bec",
"56828eae-035a-4396-ba07-51c66d680a04"
]
}
]
},
"created_at": "2023-10-18T12:08:09.575388Z",
"last_updated": "2023-10-18T12:08:09.575388Z",
"modified_by": "user@cloudflare.com"
}
],
"success": true,
"errors": [],
"messages": []
}

メンテナンス

トークン設定の更新

一定の期間ごとにキーをローテーションすることがベストプラクティスです。キーを更新するために、Cloudflareは各設定に最大4つのキーを許可します。これにより、既存のキーに新しいキーを追加できます。新しいキーのみでJWTを発行し、一定の期間後に古いキーを削除することができます。さらに、この機能により、テストまたは開発用のキーを本番用のキーと並行して展開できます。

キーの更新に必要な入力は、初期キーを提供したときと同じで、資格情報キーを使用し、JWKである必要があります。

キーを更新するには、PUTコマンドを使用します。

cURLを使用した例
curl --request PUT \
'https://api.cloudflare.com/client/v4/zones/{zone_id}/api_gateway/token_validation/{config_id}/credentials' \
--header 'Content-Type: application/json' \
--data '{
"keys": [
{
"kty": "EC",
"use": "sig",
"kid": "test",
"x": "-0LNzBheJPn-Zy6JmanTIUX7xc3jgqU714IQY0oU6mw",
"y": "KONxBybUcRsJQmtu17jMAHsILSw009AuU3ulfUGv3FI",
"alg": "ES256"
},
{
"kty": "EC",
"crv": "P-256",
"kid": "test-2",
"x": "iIbPRbOeLzjGPvv7iwmzCOTU03R0xDqbenp2D6GUcWo",
"y": "tDkEh95PnfWwIXciCtdBBVA7wfghx_egmZ1Zcvu2lWw",
"alg": "ES256"
}
]
}'

{zone_id}を関連するゾーンIDに置き換え、認証情報ヘッダーを追加してください。

トークン検証ルールの更新

トークン検証ルールは、PATCHリクエストで更新できます。単一のPATCHリクエストで複数のルールを更新できます。

PATCHリクエストは、リクエストボディ内のJSON配列として指定されます。その配列内の各アイテムは、idによって定義された単一のルールへの更新を含みます。

以下の例は、1つのルールを更新し、別のルールを無効にします:

cURLを使用した例
curl --request PATCH \
"https://api.cloudflare.com/client/v4/zones/{zone_id}/api_gateway/token_validation/rules" \
--header "Content-Type: application/json" \
--data '[
{
"id": "714d3dd0-cc59-4911-862f-8a27e22353cc",
"action": "log",
"title": "更新されたタイトル"
},
{
"id": "7124f9bc-d6b5-430d-b488-b6bc2892f2fb",
"enabled": false
}
]'

ルールは、PATCHボディ内に位置フィールドを設定することで順序を変更できます。

この例では、ルール714d3dd0-cc59-4911-862f-8a27e22353ccをルール7124f9bc-d6b5-430d-b488-b6bc2892f2fbの後に配置します:

cURLを使用した例
curl --request PATCH \
"https://api.cloudflare.com/client/v4/zones/{zone_id}/api_gateway/token_validation/rules" \
--header 'Content-Type: application/json' \
--data '[
{
"id": "714d3dd0-cc59-4911-862f-8a27e22353cc",
"position": {
"after": "7124f9bc-d6b5-430d-b488-b6bc2892f2fb"
}
}
]'

この例では、ルール714d3dd0-cc59-4911-862f-8a27e22353ccをルール7124f9bc-d6b5-430d-b488-b6bc2892f2fbの前に配置します:

cURLを使用した例
curl --request PATCH \
"https://api.cloudflare.com/client/v4/zones/{zone_id}/api_gateway/token_validation/rules" \
--header 'Content-Type: application/json' \
--data '[
{
"id": "714d3dd0-cc59-4911-862f-8a27e22353cc",
"position": {
"before": "7124f9bc-d6b5-430d-b488-b6bc2892f2fb"
}
}
]'

JWT検証の実行

以下は、JWT検証が受信リクエストを処理する方法の概要です:

  1. 受信リクエストから構成に従ってJWTを抽出します。
  2. JWTをデコードし、JWTのヘッダーKIDクレームを探します。
  3. KIDとALGクレームを使用して、提供されたキーのリストから正しいキーを見つけます。
  1. 選択したキーを使用して署名を確認することで、JWTの真正性を検証します。
  2. JWTにEXPクレーム(有効期限)が含まれている場合、JWTが期限切れでないことを検証します。
  1. JWTにNBFクレーム(有効前時間)が含まれている場合、JWTがすでに有効であることを検証します。
  1. 最終的な検証結果とトークンが存在したかどうかは、ポリシーの設定されたアクション(log/block)を適用するWAFに提供されます。