跳到主要内容
版本:Dev

JWT 认证

AISIX 可以使用短期 JSON Web Token(JWT)凭证认证 Agent,无须使用长期调用方 API Key。信任服务提供方会根据 JSON Web Key Set(JWKS)中发布的签名 Key 或共享密钥来验证每个 Token。每个经过验证的外部身份都会映射到调用方 API Key,并继承该 Key 的模型访问权限、限流和用量归因。在 AISIX Enterprise 和 AISIX Cloud 中,映射后的 Key 还会携带预算。

基于 JWKS 的服务提供方包括 Keycloak、Entra ID、Okta、Auth0 和其他兼容 OIDC 的身份服务提供方。AISIX 还可以验证由与网关共享密钥的签发者签署的 HMAC Token。无论采用哪种方式,AISIX 都会为每个请求验证 Token 签名和声明,Agent 不需要调用方 API Key 的明文值。

面向人工运维人员的控制台单点登录和面向 Agent 请求的网关 JWT 认证彼此独立,配置其中一项不会影响另一项。

工作原理​

当环境中至少存在一个已启用的信任服务提供方时,AISIX 会检查每个请求的 Bearer Token:

  1. 如果 Bearer 是 JWT,其 iss(签发者)声明会选择信任服务提供方:当 iss 与某个已启用服务提供方的 issuer 相等时,仅由该服务提供方验证此 Token。签发者与所有已启用服务提供方均不匹配的 Token 只会到达未指定签发者的已启用共享密钥服务提供方,若其中没有一个能通过验证,则该 Token 被拒绝。
  2. AISIX 使用服务提供方的 JSON Web Key Set(JWKS)验证 Token 签名;如果该服务提供方配置了共享密钥,则改用该密钥验证。随后验证注册声明:始终必需的 exp(过期时间)、仅在服务提供方配置了接受的受众时校验的 aud(受众),以及存在时的 nbf(生效时间)。
  3. 执行服务提供方的 required_scopes 和 bound_claims 要求。
  4. 服务提供方身份声明的值(默认为 sub)会选择 jwt_subject 与该值相等,且 jwt_provider 指向此服务提供方的调用方 API Key。随后请求会以此 Key 的身份运行。将绑定限定到服务提供方,可以防止第二个受信任服务提供方签发冒充此服务提供方身份的 Token。
  5. 当没有 Key 直接绑定该身份时,服务提供方的 Claim 映射——按优先级排序、匹配已验证声明的规则——可以把请求解析到一把既有的 Key,让一整组身份共享一把受治理的 Key 而无需逐个注册。既未命中绑定也未命中映射的 Token 会被拒绝。

未通过验证或无法映射到调用方 API Key 的 Token 会在请求到达服务提供方、MCP 服务器或向量存储前被 AISIX 拒绝。对于 JWKS 服务提供方,身份服务提供方的签名 Key 轮换会自动生效,无须重启网关。

前置条件​

开始前,请准备以下内容:

  • 以下任一配置路径:
    • AISIX Enterprise 或 AISIX Cloud 环境,以及具有 write 作用域的 Admin Token。使用 AISIX Enterprise 时,请先完成 AISIX Enterprise 快速入门;如需申请 AISIX Cloud 访问权限,请联系 API7。
    • 加载声明式 resources.yaml 文件的开源 AISIX 网关。
  • 向 Agent 签发 JWT 的系统,以及与其签名方式相应的验证材料:
    • 使用 JWKS 验证时,请准备预期的签发者,以及其 JWKS 端点 URL 或 OIDC 发现文档(<issuer>/.well-known/openid-configuration)。
    • 使用 HMAC 签名时,请准备共享密钥。其 UTF-8 编码长度必须至少为 32 字节;预期的签发者和受众可选。
  • 调用方可以使用的模型别名;控制面工作流还需要其模型 ID。如果尚未创建,请先配置服务提供方密钥和模型别名。
  • curl 和 jq。开源 AISIX 网关还需要 OpenSSL,以运行下文的凭证生成命令。

使用 JWKS 验证的服务提供方必须使用 AISIX 支持的非对称算法签署 Token:RSA(RS256、RS384、RS512、PS256、PS384 或 PS512)、ECDSA(ES256 或 ES384),或 EdDSA,并会拒绝 HMAC 签名的 Token。如果需要信任使用共享密钥签名的签发者,请改为给服务提供方配置 hmac_secret,详见共享密钥(HMAC)服务提供方。

配置 JWT 认证​

请使用与你的部署方式对应的管理路径,配置信任服务提供方和绑定身份的调用方 API Key。

选择信任服务提供方设置​

AISIX Enterprise、AISIX Cloud 和开源 AISIX 网关采用相同的信任设置,但对签发者唯一性的约束方式不同:

字段说明
issuer预期的 iss 声明,会与 Token 进行精确比较。已配置的签发者在 AISIX 环境中必须唯一;在资源文件中,设置了签发者的已启用服务提供方必须使用不同的值。使用 JWKS 验证时必填;设置 hmac_secret 时可选。未指定签发者的共享密钥服务提供方不会校验 iss。
audiences接受的 aud 值。使用 JWKS 验证时必须至少配置一个值,且 Token 必须包含匹配值。设置 hmac_secret 时,省略该字段或使用空列表即可跳过受众校验。
jwks_uri获取签名 Key 的端点。省略时,从签发者的 OIDC 发现文档解析。不能与 hmac_secret 同时设置。
hmac_secret共享密钥,设置后该服务提供方改用 HMAC 验证。使用 JWKS 验证的服务提供方请省略此字段。详见共享密钥(HMAC)服务提供方。
identity_claim声明路径,其值用于选择调用方 API Key,会与每个 Key 的 jwt_subject 匹配,例如 resource_access.account。默认 sub。
required_scopes必须全部出现在 Token scope 声明中的作用域,该声明可以是空格分隔字符串或数组。
bound_claims额外的声明要求。每个 Key 是一个声明路径。字符串声明必须等于一个预期值,数组声明必须包含一个预期值。
tag_claims每个请求从已验证的 Token 读取的成本归属标签,形式为标签键到声明路径的对象,例如 {"department": "department", "subsidiary": "org.subsidiary"}。按标签键逐个比较,这样读取的值优先于调用方 API Key、其团队和其成员上的值。键须匹配 ^[a-z][a-z0-9_]{0,62}$,路径不能为空,最多 32 条。在 AISIX Enterprise 和 AISIX Cloud 中,每个键都必须已在组织中声明。需要 1.9.0 或更高版本的网关。详见从 JWT Claim 读取标签。
leeway_secs基于时间的声明所允许的时钟偏差,范围为 0 到 300 秒。默认 0。
login网关让只配置了 URL 的 MCP 客户端的用户登录时所用的 OAuth 客户端(client_id,可选 client_secret 和 scopes)。不能与 hmac_secret 同时设置,且一个环境中只能有一个已启用的服务提供方带有它。参见 MCP 交互式登录。
enabled服务提供方是否参与认证。默认 true。
URL 中的用户信息并非受保护的密钥

不要在 issuer 或 jwks_uri URL 中嵌入 user:password@ 等凭据。网关公开实现不会拦截这类用户信息,且会记录签发者;控制面 API 响应、审计记录和其他日志也可能暴露配置的 URL。请使用不带凭据的 HTTPS 端点,并通过网络层访问控制保护。

对于 JWKS 服务提供方,省略 jwks_uri 时,AISIX 会从签发者的发现文档解析并缓存签名 Key 端点。如果网关无法访问发现文档,请显式提供 jwks_uri。

声明路径​

identity_claim、bound_claims、tag_claims 以及 Claim 映射条件中的 claim 都用同样的方式读取声明路径。整个字符串先当作一个完整的顶层声明名读取,所以 https://example.com/department 这样带点的名字可以使用。Token 中没有这个名字的声明时,再用点遍历嵌套对象,所以 resource_access.account 读取 resource_access 内的 account。

如果 Token 同时带有名为 a.b 的声明和嵌套的 a: {"b": ...},路径 a.b 读取前者。1.9.0 之前的网关只用点遍历。

AISIX Enterprise 或 AISIX Cloud​

导出基础 URL、Admin Token、环境 ID 和模型 ID:

# AISIX_CP 是 Admin API 基础 URL;应包含 /api,且不含尾部斜杠
# 本地私有化部署快速入门使用 http://localhost:8080/api
export AISIX_CP="YOUR_AISIX_CONTROL_PLANE_API_URL"
export AISIX_TOKEN="YOUR_ADMIN_TOKEN"
export ENV_ID="YOUR_ENVIRONMENT_ID"
export MODEL_ID="YOUR_MODEL_ID"

注册信任服务提供方​

本示例使用 JWKS 验证。请提供签发者和至少一个接受的受众:

curl -sS -X POST "$AISIX_CP/environments/$ENV_ID/oidc_providers" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "corp-keycloak",
"issuer": "https://sso.example.com/realms/agents",
"audiences": ["aisix-gateway"],
"required_scopes": ["ai.access"],
"bound_claims": {
"department": "ai-lab"
}
}' | jq

响应会返回已创建的服务提供方,包括 AISIX 填入的默认值:

{
"oidc_provider": {
"id": "b2c3d4e5-6789-4abc-def0-123456789abc",
"env_id": "9be9891a-6a53-4bd8-a897-a03fe38a1ca5",
"name": "corp-keycloak",
"issuer": "https://sso.example.com/realms/agents",
"audiences": ["aisix-gateway"],
"identity_claim": "sub",
"required_scopes": ["ai.access"],
"bound_claims": {
"department": "ai-lab"
},
"leeway_secs": 0,
"enabled": true,
"created_at": "2026-07-27T12:00:00Z",
"updated_at": "2026-07-27T12:00:00Z"
}
}

将调用方 API Key 绑定到身份​

创建或更新调用方 API Key,并同时设置以下两个字段:

  • jwt_subject:已验证 Token 映射到的外部身份。将它设为 Token 签发者在服务提供方的 identity_claim 所指定声明中写入的值。
  • jwt_provider:允许声明该主体的信任服务提供方名称。只有此服务提供方签发的 Token 才能映射到该 Key。
curl -sS -X POST "$AISIX_CP/environments/$ENV_ID/api_keys" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"display_name": "billing-agent",
"allowed_models": ["'"$MODEL_ID"'"],
"jwt_subject": "agent-billing-01",
"jwt_provider": "corp-keycloak"
}' | jq

jwt_provider 和 jwt_subject 组合在环境中唯一,并且两者必须一起设置。请为每个 Agent 身份分配独立的调用方 API Key,使模型访问权限、限流和用量归因彼此独立。在 AISIX Enterprise 和 AISIX Cloud 中,每个身份还会继承该 Key 的预算。Agent 使用自己的 JWT 认证,因此无须分发 Key 的明文值。

开源 AISIX 网关​

对于开源 AISIX 网关,请在 resources.yaml 中声明 OIDC 服务提供方和绑定 JWT 的调用方 API Key。allowed_models 中的模型别名也必须在文件中定义:

resources.yaml
_format_version: "1"

provider_keys:
- display_name: openai-prod
provider: openai
adapter: openai
api_key: ${OPENAI_API_KEY}
api_base: https://api.openai.com/v1

models:
- display_name: gpt-4o-prod
provider: openai
model_name: gpt-4o
provider_key: openai-prod

oidc_providers:
- name: corp-keycloak
issuer: https://sso.example.com/realms/agents
audiences: ["aisix-gateway"]
required_scopes: ["ai.access"]
bound_claims:
department: ai-lab

api_keys:
- display_name: billing-agent
key_env: BILLING_AGENT_KEY
allowed_models: ["gpt-4o-prod"]
jwt_subject: agent-billing-01
jwt_provider: corp-keycloak

❶ api_key 通过 OPENAI_API_KEY 提供模型服务提供方凭证。

❷ key_env 指定保存调用方 API Key 明文值的环境变量名称。

加载任何调用方 API Key 时,AISIX 都要求提供调用方凭证,即使 Agent 只使用 JWT 认证。请为网关进程设置两个变量,并且不要把 BILLING_AGENT_KEY 分发给 Agent:

export OPENAI_API_KEY="YOUR_PROVIDER_API_KEY"
export BILLING_AGENT_KEY="$(openssl rand -hex 32)"

按照资源文件参考校验并加载文件。加载成功后,使用下一节所示的相同 JWT 请求。

共享密钥(HMAC)服务提供方​

部分签发者使用双方共同持有的密钥签署 Token,而不是使用 JWKS 中发布的密钥对。给信任服务提供方配置 hmac_secret 即可验证这类 Token。该字段可选,设置后只会改变这一个服务提供方的行为:

  • 仅接受 HS256、HS384 或 HS512 签名的 Token。
  • 不获取任何内容:没有 JWKS 请求,也没有 OIDC 发现。不能设置 jwks_uri。
  • issuer 和 audiences 变为可选。设置 issuer 时,iss 必须与其匹配;audiences 列表非空时,aud 必须包含其中一个值。省略任一字段会跳过对应校验,空受众列表也会跳过受众校验。

其余行为与 JWKS 服务提供方一致。exp 声明仍然必需。身份声明、权限范围和声明要求、Claim 映射、时钟偏差容差,以及调用方 Key 绑定都保持原有工作方式。

未配置 hmac_secret 的服务提供方行为不变:获取签名 Key,只接受前置条件一节列出的非对称算法,并拒绝 HMAC 签名的 Token。

条件允许时优先使用非对称签名

使用共享密钥时,网关持有的密钥同样可以签发 Token。密钥泄露会让攻击者能够冒充该签发者所能声明的任意身份。只要签发者能够提供 JWKS,就优先使用 JWKS 服务提供方。对于开源网关,请通过环境变量引用密钥,不要把密钥写入文件。

密钥处理​

密钥的 UTF-8 字节会原样作为 HMAC Key,不做 base64 解码,也不做任何派生,因此签发者必须使用完全相同的字节串签名。密钥长度至少为 32 字节。

每个服务提供方只持有一个密钥。轮换方式是更新该服务提供方的密钥;变更到达网关后,使用旧密钥签名的 Token 立即无法通过验证。

服务提供方选择​

当 Token 的 iss 与某个已启用服务提供方的 issuer 相等时,仅由该服务提供方验证此 Token。此时验证模式或算法不匹配会返回 401,不会回退到其他服务提供方。

否则,AISIX 会按服务提供方名称顺序,逐个尝试所有未指定 issuer 的已启用共享密钥服务提供方,第一个验证通过的生效。尝试个数没有上限。如果都无法通过验证,该 Token 会被拒绝。JWKS 服务提供方永远不会以这种方式被尝试,因为该模式下 issuer 是必填项。

请为每个未指定签发者的共享密钥服务提供方配置各自不同的密钥。共享同一密钥的服务提供方可以验证相同的 Token。按名称排在前面的服务提供方会胜出,因此另一个服务提供方的受众、权限范围和声明要求永远不会生效。

配置共享密钥服务提供方​

在 AISIX Enterprise 和 AISIX Cloud 中,创建服务提供方时携带 hmac_secret。下面的示例未指定签发者和受众,因此不会校验 Token 的 iss 和 aud 声明:

curl -sS -X POST "$AISIX_CP/environments/$ENV_ID/oidc_providers" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "partner-hmac",
"hmac_secret": "YOUR_SHARED_SECRET_OF_AT_LEAST_32_BYTES",
"required_scopes": ["ai.access"]
}' | jq

该密钥只写不读,读取时永远不会返回,而是返回 "hmac_secret_set": true:

{
"oidc_provider": {
"id": "c3d4e5f6-7890-4abc-def0-123456789abc",
"name": "partner-hmac",
"audiences": [],
"identity_claim": "sub",
"required_scopes": ["ai.access"],
"hmac_secret_set": true,
"leeway_secs": 0,
"enabled": true
}
}

更新时,省略 hmac_secret 表示保留已存储的密钥,传入新值表示替换,传入 null 表示清除。清除后该服务提供方切换回 JWKS 模式,此时 issuer 和至少一个受众变为必填。

在控制台中,服务提供方表单提供签名校验方式选项:JWKS / OIDC 发现或共享密钥(HMAC)。共享密钥字段以密码形式输入,保存后不再回显;编辑已配置密钥的服务提供方时,留空表示保留原密钥。服务提供方列表会显示各自的校验方式。

对于开源网关,请在 resources.yaml 的 oidc_providers 条目中通过环境变量提供密钥,使明文不出现在文件里:

resources.yaml(OIDC 服务提供方)
oidc_providers:
- name: partner-hmac
hmac_secret: ${JWT_HMAC_SECRET}
required_scopes: ["ai.access"]
export JWT_HMAC_SECRET="YOUR_SHARED_SECRET_OF_AT_LEAST_32_BYTES"

配置错误​

以下配置不一致的服务提供方会被 AISIX 拒绝:

  • 同时设置了 jwks_uri 和 hmac_secret。
  • 未设置 hmac_secret,同时缺少 issuer 或至少一个受众。
  • hmac_secret 短于 32 字节。

AISIX Cloud Admin API 对以上情况均返回 400。在资源文件中,出错的条目会在加载时被拒绝,并由配置状态报告,同时计入 aisix_config_rejected_resources。

网关版本要求​

共享密钥服务提供方要求 AISIX 网关版本为 1.5.0 或更高。AISIX Enterprise 和 AISIX Cloud 支持的所有网关版本(1.6.0 及更高)都满足这一要求。低于 1.6.0 的已连接网关在保存时不做检查,请先将其升级。参见混合版本行为。

认证请求​

让 Agent 从签发系统获取 Token。设置模型别名和 Token,然后像使用调用方 API Key 一样,在代理 API 上发送该 Token:

# AISIX_PROXY 是网关源站;请勿包含尾部斜杠或端点路径
# 本地快速入门使用 http://127.0.0.1:3000。
export AISIX_PROXY="YOUR_AISIX_GATEWAY_URL"
export MODEL_ALIAS="YOUR_MODEL_ALIAS"
export AGENT_JWT="eyJhbGciOiJSUzI1NiIsImtpZCI6..."

curl -sS -X POST "$AISIX_PROXY/v1/chat/completions" \
-H "Authorization: Bearer $AGENT_JWT" \
-H "Content-Type: application/json" \
-d '{
"model": "'"$MODEL_ALIAS"'",
"messages": [{"role": "user", "content": "Hello"}]
}' | jq

AISIX 会验证 Token 并将其映射到 billing-agent Key:Token 的 sub 声明 agent-billing-01 匹配 Key 的 jwt_subject,Token 签发者解析到 Key jwt_provider 所指定的 corp-keycloak 服务提供方。随后请求会以该 Key 的权限运行。Token 的 aud 必须包含 aisix-gateway,还必须携带服务提供方要求的 ai.access 作用域和 department: ai-lab 声明。

拒绝原因​

在 OpenAI 风格代理路由上,被拒绝的 Token 会携带稳定的 error.code,客户端无须解析消息即可处理。Anthropic 风格路由会省略 code,并使用 HTTP 状态码和兼容 Anthropic 的 error.type;详见响应头和错误码。

OpenAI 风格 error.codeHTTP 状态含义
jwt_expired401Token 的 exp 截止时间已过,请获取新 Token。
jwt_invalid401Token 格式错误,或未通过签发者、签名、签名算法、受众、必需声明或生效时间验证。
jwt_claims_rejected403Token 有效,但不满足服务提供方的 required_scopes 或 bound_claims。
jwt_identity_unmapped401配置的身份声明缺失或不是字符串,或者该身份无法解析到任何 Key——没有调用方 API Key 的 jwt_provider 和 jwt_subject 与之匹配,也没有 Claim 映射命中。请检查 Token 声明、Key 绑定和映射。
jwks_unavailable503AISIX 无法解析或获取服务提供方的签名 Key。请检查 OIDC 发现文档或 JWKS 端点,然后重试。

Key 轮换​

本节适用于使用 JWKS 验证的服务提供方。共享密钥服务提供方不获取任何内容,轮换方式是更新其 hmac_secret。

身份服务提供方引入新签名 Key 时,无法识别的 Key ID 会触发 JWKS 刷新。无须更改配置或重启网关。

AISIX 会合并对同一 OIDC 发现文档或 JWKS URL 的并发出站请求。当缓存为空、已配置的 JWKS URL 发生变化,或某个 Token 使用新轮换的 Key 时,请求会等待共用的获取操作。能够使用过期缓存结果的请求会在刷新期间继续处理。

无论获取成功还是失败,AISIX 都会在至少 1 秒后才再次获取同一发现文档或 JWKS URL。在此间隔内需要新信任材料的请求可能需要重试。

AISIX 将缓存的发现结果和 Key 集合视为 10 分钟内有效。超过该间隔后,下一次认证请求会触发刷新。刷新后的集合不再包含已退役 Key 后,由该 Key 签名的 Token 将无法认证。如果刷新时发现文档或 JWKS 端点不可用,AISIX 会继续使用上次成功获取的结果。现有认证可以使用缓存的 Key 继续进行,但退役 Key 仍受信任,直到后续刷新成功。

更新或删除信任服务提供方​

AISIX Enterprise 或 AISIX Cloud​

使用 Admin API 更新现有服务提供方。例如,可以将其禁用,以停止信任其 Token,同时保留配置:

export OIDC_PROVIDER_ID="b2c3d4e5-6789-4abc-def0-123456789abc"

curl -sS -X PATCH "$AISIX_CP/environments/$ENV_ID/oidc_providers/$OIDC_PROVIDER_ID" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{"enabled": false}' | jq

将 enabled 设置为 true 可以重新信任该服务提供方。还可以通过同一 PATCH 操作更新签发者、可接受受众、JWKS 端点、共享密钥、身份声明、必需权限范围、绑定声明、标签声明或时钟偏差容差。服务提供方名称在创建后不能更改。

删除服务提供方会彻底移除信任:

curl -sS -X DELETE "$AISIX_CP/environments/$ENV_ID/oidc_providers/$OIDC_PROVIDER_ID" \
-H "Authorization: Bearer $AISIX_TOKEN" | jq

删除服务提供方不会影响调用方 API Key 或其 jwt_subject 绑定。这些 Key 仍可使用明文值认证,之后也可以重新关联到新的服务提供方。

删除服务提供方或修改其 issuer、identity_claim,还会移除为其用户存储的上游凭证。这些用户需要重新授权每个使用按用户登录的 MCP 服务器,其中通过网关登录的用户还需要重新登录。参见哪些变更会断开用户。

开源 AISIX 网关​

编辑 resources.yaml 的 oidc_providers 下对应服务提供方。设置 enabled: false 可以在保留配置的同时将其禁用;更改字段可以更新信任策略;移除条目可以删除服务提供方。

禁用或移除服务提供方后,调用方 API Key 仍保留在 api_keys 中,其明文值可以继续用于身份认证。如需同时移除 JWT 身份映射,请从该 Key 中同时删除 jwt_subject 和 jwt_provider。

每次更改后,请验证并重新加载文件。完整工作流参见重新加载资源文件。

后续步骤​

  • JWT Claim 映射:通过按优先级排序的声明规则放行一整类身份(部门、群组、应用),而无需逐一绑定。
  • Keycloak 集成:从 Keycloak Realm 到映射且归因的请求,一份经过完整验证的端到端指南。
  • 调用方 API Key:管理每个映射身份继承的模型访问权限和其他控制项。
  • 成本归属标签:把成本归属到从 Token 读取的值,例如部门。
  • API Key 与模型限流:限制使用 JWT 认证的调用方的请求量或 Token 用量。
  • 配置传播:了解配置更改如何到达 AISIX 网关。