跳转到内容
搜索文档

通过 API 配置 JWT 验证

最后更新 查看 MarkdownAgent 设置

使用 Cloudflare API 配置 JWT 验证,这需要令牌配置和令牌验证规则。

令牌配置

令牌配置定义了 JSON Web 密钥集 (JWKs),用于验证客户端发送的 JSON Web 令牌 (JWT) 以及关于这些 JWT 在请求中发送位置的信息。

令牌配置需要以下信息:

字段名称 描述 示例 备注
title 配置的人类可读名称,允许您快速识别配置的目的。 Production JWT configuration 限制为 50 个字符。
description title 给出更多细节的人类可读描述,用作允许客户更好记录配置用途的手段。 This configuration is used for all endpoints in endpoint management and checks the JWT in the authorization header. 限制为 500 个字符。
token_sources 请求中可能包含 JWT 的位置列表。 http.request.headers[\"authorization\"][0]
http.request.cookies[\"Authorization\"][0]
请参阅下面的信息
token_type 指定要验证的令牌类型。 jwt 目前仅支持 jwt
credentials 描述应该用于验证 JWT 的加密公钥。此字段必须是 JSON Web 密钥。 请参阅下面的示例。 请参阅下面的信息

令牌来源

每一项都必须是解析为字符串的规则集引擎 (Ruleset Engine) 表达式。

目前支持的字段是 http.request.headershttp.request.cookies

您最多可以设置四个令牌来源。如果请求设置了这些字段中的多个,则只会使用一个。请求令牌中前导的 Bearer: 字符串会被自动忽略。

有关使用规则集引擎字段的详细信息,请参阅规则集引擎文档

凭据 (Credentials)

API Shield 支持 RS256RS384RS512PS256PS384PS512ES256ES384 类型的凭据。RSA 密钥必须至少为 2048 位。每个 JSON Web 密钥都必须有一个 “KID”,该 “KID” 也必须存在于 JWT 的标头中,以允许 API Shield 对其进行匹配。

我们允许最多 4 个不同的密钥,以帮助进行密钥轮换。

Cloudflare 将从每个密钥中删除任何不必要的字段,并将放弃我们不支持的密钥。

强烈建议验证 API 调用的输出,以检查结果密钥是否符合预期。

令牌配置 JSON 对象

下面的示例展示了一个 JSON 对象,其中包含使用 Cloudflare API 创建令牌配置所需的所有信息。如果您想创建用于测试的 JWKs,请参阅 mkjwk JSON Web Key Generator

示例json
{
	"title": "Production JWT configuration",
	"description": "This configuration checks the JWT in the authorization header or cookie.",
	"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 的示例bash
curl "https://api.cloudflare.com/client/v4/zones/{zone_id}/token_validation/config" \
--header 'Content-Type: application/json' \
--data '{
    "title": "Production JWT configuration",
    "description": "This configuration checks the JWT in the authorization header or cookie.",
    "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 创建令牌验证规则时,它将用于引用令牌配置。

响应示例json
{
	"result": {
		"id": "d5902294-00c3-4aed-b517-57e752e9cd58",
		"token_type": "JWT",
		"title": "Production JWT configuration",
		"description": "This configuration checks the JWT in the authorization header or cookie.",
		"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 一个人类可读的名称,允许您快速识别它。 JWT validation on v1 and v2.example.com 限制为 50 个字符。
description title 给出更多细节的人类可读描述,有助于记录它。 Log requests without a valid authorization header. 限制为 500 个字符。
action 对不符合 expression 的请求采取的防火墙操作。 log 可能的值:logblock
enabled 启用或禁用该规则。 true 可能的值:truefalse
expression 规则的安全策略。 is_jwt_valid ("00170473-ec24-410e-968a-9905cf0a7d03") 使用 Cloudflare API 创建规则时,请确保对任何引号进行转义。
请参阅下面的定义安全策略
selector 配置此规则涵盖哪些操作。 请参阅下面的将规则应用于操作

选择器 (Selectors)

选择器控制您的令牌验证规则的范围。

如果您只需要在顶级域的特定主机名或子域上进行 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") 将被触发。

这些表达式类似于规则集引擎中使用的表达式,但有一些关键区别:

  • 与规则集表达式相反,如果表达式的评估结果为 false,则会触发令牌验证规则操作。
  • 令牌验证规则可以使用引用令牌配置的专用函数。

运算符(如 orandeq 等)在表达式中的使用方式与规则集引擎中使用的表达式相同。

以下函数可用于与请求中的 JWT 令牌进行交互:

常见用例

请参阅以下示例用例以了解要使用哪种安全策略。对于大多数用例,Cloudflare 建议在您的 API 中要求提供有效的令牌,并使用选择器排除任何用于建立或刷新令牌的路径。

要求提供令牌

如果请求缺少 JWT,表达式 is_jwt_present("51231d16-01f1-48e3-93f8-91c99e81288e") 将触发操作。

它可以与令牌验证规则中的 log 操作结合使用,以记录缺少身份验证标头的请求。

要求提供有效的令牌

如果请求没有有效的 JWT,表达式 is_jwt_valid("51231d16-01f1-48e3-93f8-91c99e81288e") 将触发操作。

它可以与令牌验证规则中的 block 操作结合使用,以阻止没有凭据或凭据无效的请求。

要求提供两个可能令牌中的至少一个

如果请求没有至少一个有效的令牌,表达式 is_jwt_valid("51231d16-01f1-48e3-93f8-91c99e81288e") or is_jwt_valid("fddfc39e-3686-4683-ab23-bf917da6bb43") 将触发操作。

如果您需要将 JWKs 拆分为多个令牌配置,可能会发生这种情况。

要求提供有效的令牌,但忽略没有令牌的请求

如果请求包含无效令牌,表达式 is_jwt_valid("51231d16-01f1-48e3-93f8-91c99e81288e") or not is_jwt_present("51231d16-01f1-48e3-93f8-91c99e81288e") 将触发操作,从而忽略完全没有令牌的请求。

将规则应用于操作

一个操作只能应用一个令牌验证规则。如果一个操作被多个规则覆盖,则优先级最高的规则将生效。

您可以使用 selector 字段配置对哪些操作强制执行 JWT 验证。

例如,以下选择器将把规则应用于 v1.example.comv2.example.com 中的所有操作,但这些主机上的两个操作除外:

选择器示例json
{
	"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}/token_validation/rules/preview 端点查看此规则所涵盖的操作:

使用 cURL 的示例bash
curl --request PUT \
'https://api.cloudflare.com/client/v4/zones/{zone_id}/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 字段可以是 ignoredexcludedincluded。Included 操作将匹配您指定的主机名选择器。Excluded 操作将匹配您在选择器中指定的操作 ID。Ignored 操作是那些与选择器中指定的任何内容都不匹配的操作。

结果json
{
	"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
	}
}

stateincluded 的操作将被令牌验证规则覆盖。该响应还在 result.selected_hosts 中显示包含的主机名,并在 result.available_hosts 中显示所有区域操作使用的所有主机名。

您也可以在请求正文中发送一个空对象:

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

该响应将显示所有区域操作和所有可能的主机,您可以使用它们来构建自己的选择器。

令牌验证规则 JSON 对象

下面的示例展示了一个 JSON 对象,其中包含使用 Cloudflare API 创建令牌验证规则所需的所有必要信息。

将任何令牌配置 ID 和操作 ID 替换为您的区域中存在的 ID。

令牌验证规则 JSON 示例json
[
	{
		"title": "JWT Validation on v1 and v2.example.com",
		"description": "Log requests without a valid authorization header.",
		"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。

单次请求可以创建多个规则。为此,请在请求正文的 JSON 数组中传递多个规则对象。

使用 cURL 的示例bash
curl "https://api.cloudflare.com/client/v4/zones/{zone_id}/token_validation/rules/bulk" \
--header 'Content-Type: application/json' \
--data '[
    {
        "title": "JWT Validation on v1 and v2.example.com",
        "description": "Log requests without a valid authorization header.",
        "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,它可以用于编辑或删除现有规则。

结果json
{
	"result": [
		{
			"id": "5ec7c417-6964-4b24-b82c-a23a7ec8f90c",
			"title": "JWT Validation on v1 and v2.example.com",
			"description": "Log requests without a valid authorization header.",
			"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": "[email protected]"
		}
	],
	"success": true,
	"errors": [],
	"messages": []
}

维护

更新令牌配置

最佳做法是在一段时间后轮换密钥。为了支持更新密钥,Cloudflare 允许每个配置最多包含四个密钥。这允许您将第二个新密钥添加到已经存在的密钥中。您可以开始仅使用新密钥签发 JWT,并在一段时间后删除旧密钥。此外,此功能允许在生产密钥旁边部署测试或开发密钥。

更新密钥的输入与创建配置时提供初始密钥相同,即需要是一个 JWK。

使用 PUT 命令更新密钥。

使用 cURL 的示例bash
curl --request PUT \
'https://api.cloudflare.com/client/v4/zones/{zone_id}/token_validation/config/{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 定义)的更新。

以下示例更新了一个规则并禁用了另一个规则:

使用 cURL 的示例bash
curl --request PATCH \
"https://api.cloudflare.com/client/v4/zones/{zone_id}/token_validation/rules/bulk"  \
--header "Content-Type: application/json" \
--data '[
    {
        "id": "714d3dd0-cc59-4911-862f-8a27e22353cc",
        "action": "log",
        "title": "updated title"
    },
    {
        "id": "7124f9bc-d6b5-430d-b488-b6bc2892f2fb",
        "enabled": false
    }
]'

规则可以通过在 PATCH 正文中设置 position 字段来重新排序。

此示例将规则 714d3dd0-cc59-4911-862f-8a27e22353cc 放置在规则 7124f9bc-d6b5-430d-b488-b6bc2892f2fb 之后:

使用 cURL 的示例bash
curl --request PATCH \
"https://api.cloudflare.com/client/v4/zones/{zone_id}/token_validation/rules/bulk" \
--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 的示例bash
curl --request PATCH \
"https://api.cloudflare.com/client/v4/zones/{zone_id}/token_validation/rules/bulk" \
--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. 最终的验证结果以及是否完全存在令牌将提供给 WAF,WAF 会应用策略配置的操作 (log/block)。

  2. Cloudflare 仪表板中针对 API Shield - Token Validation 服务的安全分析 (Security Analytics) 事件将在事件的 Token validation violations 部分中说明违规原因。

这篇文档对您有帮助吗?