跳到主要内容

JWT Claim 映射

JWT 认证可以通过 jwt_providerjwt_subject 字段,将一个外部身份绑定到一把调用方 API Key。这适用于固定的 Agent 集群,但无法扩展到由企业身份提供商为数百人声明部门、群组或应用的场景。为每个人注册一把 Key 会重复维护 IdP 的目录,而目录中的变更也不会自动传播。

Claim 映射弥补了这一缺口。映射会匹配已验证的 JWT Claim(例如部门名称或群组成员身份),并将请求解析到现有的调用方 API Key。规则放行的所有身份都会继承该 Key 的模型访问权限、工具访问权限和限流;在 AISIX Cloud 中,还会继承其预算。用量事件仍会归因到 Token 中的具体身份。

Claim 只能选择运营者已经创建的 Key。任何 Claim 值都不会成为配置:Token 无法指定上游、扩大模型允许列表或创建预算。AISIX 会拒绝既没有匹配直接绑定、也没有匹配 Claim 映射的 Token。

映射如何求值

对于每个携带 JWT Bearer 的请求,在完成 JWT 认证所述的完整信任提供商验证之后:

  1. 如果某把调用方 API Key 通过 jwt_subjectjwt_provider 直接绑定了 Token 的 Subject,请求会以该 Key 的身份运行。直接绑定对该 Subject 具有最高权威;即使该 Key 已禁用,请求也会被拒绝,映射不会覆盖它。
  2. 否则,AISIX 会评估 jwt_provider 指向已匹配信任提供商的所有已启用映射。priority 值越小越先评估,同值时按 name 排序;第一条所有 match 条件均成立的映射会选定所用的 Key。
  3. 如果没有映射匹配,请求会被拒绝并返回 jwt_identity_unmapped,不存在默认放行。

映射的 match 字段是一组必须全部成立的条件:

字段说明
claim非空的 Claim 路径。点号用于遍历嵌套对象(例如 realm_access.roles)。缺失的 Claim 永不匹配。
op使用 exact 时,Claim 必须是与 values 之一相等的字符串。使用 contains 时,Claim 必须是数组,且其字符串元素中包含 values 之一;非字符串元素会被忽略。类型与操作符不符的 Claim 永不匹配。
values一个或多个可接受的字符串,任意一个匹配即满足该条件。

jwt_provider 指定的信任提供商必须先验证 Token,AISIX 才会考虑任何映射。在 AISIX Cloud 中,映射的 Key 必须持续存在于同一环境中,因此删除被某条映射指向的 Key 会被拒绝——请先改指向或删除该映射。在声明式资源文件中,引用未知的提供商或 Key 会阻止配置加载。

前提条件

开始之前,请准备:

  • 按照 JWT 认证配置的 OIDC 信任提供商和模型。
  • 一把充当共享策略 Key 的调用方 API Key。配置允许放行的身份应继承的模型访问权限、工具访问权限和限流;在 AISIX Cloud 中,还会应用匹配的预算。
  • 选择一种配置路径:
    • AISIX Cloud:准备一个环境、已连接的网关,以及具有 write Scope 的管理员 Token,并记录策略 Key 的 ID。
    • 开源 AISIX 网关:准备完整的 resources.yaml 文件,并能够设置网关进程环境变量。
  • AISIX Cloud 工作流需要 curljq;开源工作流使用 OpenSSL 生成下文所示的策略 Key 值。

检查信任提供商要求

AISIX 会先评估信任提供商要求,再评估 Claim 映射。请删除或更新应由映射作出判断的 bound_claims 条件。在本工作流中,删除 JWT 认证示例中的 department: ai-lab 条件,因为由映射决定放行哪些部门。

保留获准身份能够满足的 required_scopes 要求。示例保留 ai.access,因此映射的 Token 必须携带该 Scope。请按照更新或删除信任提供商应用提供商变更。

配置 Claim 映射

使用与部署方式对应的管理路径配置 Claim 映射。

AISIX Cloud

导出 AISIX Cloud Admin API 连接信息、环境 ID 和策略 Key ID:

# AISIX_CP 包含 /api,末尾不带斜杠。
# 本地 On-Premises 快速入门使用 http://localhost:8080/api。
export AISIX_CP="YOUR_AISIX_CLOUD_ADMIN_API_URL"
export AISIX_TOKEN="YOUR_ADMIN_TOKEN"
export ENV_ID="YOUR_ENVIRONMENT_ID"
export POLICY_KEY_ID="YOUR_API_KEY_ID"

department Claim 等于 finance 的所有身份放行到策略 Key 下:

curl -sS -X POST "$AISIX_CP/environments/$ENV_ID/claim_mappings" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "finance-dept",
"jwt_provider": "corp-keycloak",
"priority": 100,
"match": [
{
"claim": "department",
"op": "exact",
"values": ["finance"]
}
],
"resolve": {
"api_key_id": "'"$POLICY_KEY_ID"'"
}
}' | jq

响应会回显创建的映射。如果环境中的部分网关运行的版本早于 Claim 映射特性,响应还会包含 warnings 数组。这些网关会完全跳过该规则,持续拒绝本应放行的身份,因此请先升级它们再依赖此规则。

映射字段

字段说明
name映射名称,在环境内唯一且创建后不可更改。也是优先级相同时的求值决胜依据。
jwt_provider此映射适用的 OIDC 提供商名称。映射不会匹配由其他提供商验证的 Token,因此两个提供商无法选择彼此的 Key。
priority在该提供商的映射中的非负求值顺序。数值越小越先评估,默认为 0
match1 到 16 个必须全部成立的 Claim 条件(见上表)。
resolve.api_key_id匹配请求所使用的调用方 API Key ID。
enabled映射是否参与求值。默认为 true;禁用的映射会保留但被跳过。

AISIX Cloud Admin API 接受最长 120 个字符的映射名称和提供商名称。一个映射可包含 1 到 16 个条件。每个条件的 Claim 路径最长 256 个字符,可包含 1 到 64 个可接受值,每个值最长 256 个字符。

使用 PATCH .../claim_mappings/{claim_mapping_id} 更新映射。名称不可更改,因此重命名需要删除后重新创建。使用 DELETE 删除映射。变更对新请求即时生效,无需重启网关;仅由已删除或已禁用映射放行的身份,会在网关获取变更后立即停止认证。

Dashboard 中环境的 Claim 映射 页面管理相同的规则,并按求值顺序显示规则列表。

开源 AISIX 网关

此配置扩展了 JWT 认证中的完整资源文件。保留该文件的 _format_version、服务提供方密钥和模型条目。将新的策略 Key 值设置到网关进程环境中:

export FINANCE_POLICY_KEY="$(openssl rand -hex 32)"

使用此条目替换 corp-keycloak,不要添加第二个同名提供商。它保留 ai.access Scope,同时将部门判定移交给映射:

resources.yaml(OIDC 提供商)
oidc_providers:
- name: corp-keycloak
issuer: https://sso.example.com/realms/agents
audiences: ["aisix-gateway"]
required_scopes: ["ai.access"]

finance-policy-key 添加到现有 api_keys 列表。将 finance-dept 添加到 claim_mappings;如果顶层 claim_mappings 集合不存在,只创建一次。保留两个集合中的现有条目,不要重复创建任何一个顶层集合键。

在组装后的 resources.yaml 中,resolve.api_key 按策略 Key 的 display_name 引用它:

resources.yaml(API Key 和 Claim 映射)
api_keys:
- display_name: finance-policy-key
key_env: FINANCE_POLICY_KEY
allowed_models: ["gpt-4o-prod"]

claim_mappings:
- name: finance-dept
jwt_provider: corp-keycloak
priority: 100
match:
- claim: department
op: exact
values: ["finance"]
resolve:
api_key: finance-policy-key

namejwt_providerprioritymatchenabled 字段的求值行为与 AISIX Cloud 中相同。开源 Schema 会验证名称、提供商、条件列表、Claim 路径和值列表均非空,但不应用 AISIX Cloud Admin API 的最大长度或列表大小限制。

文件加载器会在加载时解析引用,并拒绝未知的提供商或 Key 名称、空条件列表,以及 jwt_provider 指向文件中不存在的提供商的映射。拼写错误会导致加载失败,而不是静默地永不匹配。

按照重新加载资源文件验证并应用完整文件。如果 FINANCE_POLICY_KEY 是新增变量,请按照添加新的环境变量使用该变量重新创建网关。

在宿主机上导出变量并发送 SIGHUP,无法将变量添加到已运行的容器中。

若要保留映射配置但禁用它,请设置 enabled: false 并重新加载文件。若要删除映射,请删除对应条目并重新加载。删除策略 Key 前,需要删除或重新指向每个引用它的映射;可以在之前的一次重新加载中应用这些变更,也可以在同一个资源文件更新中完成。文件加载器会拒绝映射引用缺失 Key 的任何配置。

用优先级分层组合映射

规则通过优先级组合。为更精确的规则设置更小的值,使其优先作用于所描述的身份,再由更宽泛的规则处理其余身份。

对于 AISIX Cloud,先导出第二把策略 Key 的 ID,再创建更精确的映射:

export ADMIN_KEY_ID="YOUR_ADMIN_API_KEY_ID"

curl -sS -X POST "$AISIX_CP/environments/$ENV_ID/claim_mappings" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "platform-admins",
"jwt_provider": "corp-keycloak",
"priority": 50,
"match": [
{
"claim": "groups",
"op": "contains",
"values": ["platform-admin"]
}
],
"resolve": {
"api_key_id": "'"$ADMIN_KEY_ID"'"
}
}' | jq

同时携带 department: financeplatform-admin 群组的 Token 会通过优先级为 50 的 platform-admins 解析,而不是优先级为 100 的 finance-dept。需要不同有效访问控制的身份应解析到不同的策略 Key;多个映射也可以在需要授予相同访问权限时解析到同一把 Key。

对于开源网关,Keycloak 集成提供了体现相同优先级关系的完整双规则资源文件。

验证 Claim 映射

获取一个符合以下条件的 JWT:其已验证的 Claim 应匹配此映射,且其 Subject 未通过 jwt_subjectjwt_provider 直接绑定。然后请求只有预期策略 Key 才允许的模型,或者确认 AISIX Cloud 日志或已配置的导出器中出现了预期的 jwt_claim_mapping。这样可以区分映射命中与通过其他 Key 获得访问权限的情况。

还需要测试适用于规则的默认拒绝和优先级路径:

  • 发送一个既不匹配直接绑定、也不匹配任何映射的有效 JWT。在 OpenAI 风格的代理路由上,网关应返回 401,且 error.codejwt_identity_unmapped
  • 如果映射重叠,请使用没有直接绑定的 Subject,并发送同时匹配两条映射的 JWT。请求只有高优先级映射所选策略 Key 才允许的模型,或者确认预期的 jwt_claim_mapping 归因。这可以验证较小的 priority 值已生效。

有关涵盖两种配置路径的可复现 Keycloak 设置和验证矩阵,请参阅 Keycloak 集成

按身份归因用量

经映射放行的请求,其用量事件包含三个归因字段。已配置的可观测性导出器会收到相同字段:

字段说明
jwt_subjectToken 身份 Claim 的值;即使多个身份共享策略 Key,也能识别请求由谁发起。
jwt_provider验证该 Token 的信任提供商。
jwt_claim_mapping放行该请求的映射。通过 jwt_subjectjwt_provider 直接绑定的身份,此字段为空。

在 AISIX Cloud 中,这些字段也会显示在环境的 Logs 中,并包含在 CSV 导出中。Logs 页面支持按 JWT Subject 过滤,用量事件 API 上的 jwt_subjectjwt_claim_mapping 查询参数可收窄程序化读取结果。

当身份 Claim 包含姓名或电子邮件地址时,Subject 属于个人数据。将导出器与 Claim 映射一起启用之前,请检查导出器会把用量数据发送到何处。

拒绝行为

映射认证扩展了 JWT 拒绝原因表。当身份无法安全解析时,AISIX 会在已验证 Token 到达模型提供商、MCP 服务器或向量存储之前将其拒绝。

以下每种失败都会返回 HTTP 401。OpenAI 风格的路由在 error.code 中返回 jwt_identity_unmapped,而 aisix_auth_decisions_totalreason 标签会标识面向运营者的具体原因:

reason含义
jwt_identity_unmapped已验证的身份没有直接 Key 绑定,并且其信任提供商没有任何已启用映射能够匹配全部 Claim 条件。
claim_mapping_target_missing某个映射已匹配,但其目标调用方 API Key 不在网关当前有效配置中。AISIX Cloud 和资源文件验证通常会阻止这种状态。如果仍然出现,请检查配置传播和网关的有效资源。
jwt_binding_ambiguous多把调用方 API Key 具有相同的 jwt_providerjwt_subject 绑定,因此网关会以失败关闭方式拒绝,而不是继续评估映射。正常的配置验证会阻止这种状态。

后续步骤

  • Keycloak 集成:从 Keycloak Realm 到映射且归因的请求,一份经过完整验证的端到端指南。
  • JWT 认证:所有映射所基于的信任提供商验证。
  • 调用方 API Key:策略 Key 承载的模型访问权限、工具访问权限、限流,以及在 AISIX Cloud 中的预算。
  • API Key 与模型限流:为共享 Key 的流量设限。