JWT 认证
AISIX 可以使用短期 JSON Web Token(JWT)凭证认证 Agent,无须使用长期调用方 API Key。信任服务提供方会根据 JSON Web Key Set(JWKS)中发布的签名 Key 或共享密钥来验证每个 Token。每个经过验证的外部身份都会映射到调用方 API Key,并继承该 Key 的模型访问权限、限流和用量归因。在 AISIX Cloud 中,映射后的 Key 还会携带预算。
基于 JWKS 的服务提供方包括 Keycloak、Entra ID、Okta、Auth0 和其他兼容 OIDC 的身份服务提供方。AISIX 还可以验证由与网关共享密钥的签发者签署的 HMAC Token。无论采用哪种方式,AISIX 都会为每个请求验证 Token 签名和声明,Agent 不需要调用方 API Key 的明文值。
面向人工运维人员的控制台单点登录和面向 Agent 请求的网关 JWT 认证彼此独立,配置其中一项不会影响另一项。
工作原理
当环境中至少存在一个已启用的信任服务提供方时,AISIX 会检查每个请求的 Bearer Token:
- 如果 Bearer 是 JWT,其
iss(签发者)声明会选择信任服务提供方:当iss与某个已启用服务提供方的issuer相等时,仅由该服务提供方验证此 Token。签发者与所有已启用服务提供方均不匹配的 Token 只会到达未指定签发者的已启用共享密钥服务提供方,若其中没有一个能通过验证,则该 Token 被拒绝。 - AISIX 使用服务提供方的 JSON Web Key Set(JWKS)验证 Token 签名;如果该服务提供方配置了共享密钥,则改用该密钥验证。随后验证注册声明:始终必需的
exp(过期时间)、仅在服务提供方配置了接受的受众时校验的aud(受众),以及存在时的nbf(生效时间)。 - 执行服务提供方的
required_scopes和bound_claims要求。 - 服务提供方身份声明的值(默认为
sub)会选择jwt_subject与该值相等,且jwt_provider指向此服务提供方的调用方 API Key。随后请求会以此 Key 的身份运行。将绑定限定到服务提供方,可以防止第二个受信任服务提供方签发冒充此服务提供方身份的 Token。 - 当没有 Key 直接绑定该身份时,服务提供方的 Claim 映射——按优先级排序、匹配已验证声明的规则——可以把请求解析到一把既有的 Key,让一整组身份共享一把受治理的 Key 而无需逐个注册。既未命中绑定也未命中映射的 Token 会被拒绝。
未通过验证或无法映射到调用方 API Key 的 Token 会在请求到达服务提供方、MCP 服务器或向量存储前被 AISIX 拒绝。对于 JWKS 服务提供方,身份服务提供方的签名 Key 轮换会自动生效,无须重启网关。
前置条件
开始前,请准备以下内容:
- 以下任一配置路径:
- AISIX Cloud 环境,以及具有
write作用域的 Admin Token。对于本地部署,请先完成 AISIX Cloud 快速入门;如需申请混合云访问权限,请联系 API7。 - 加载声明式
resources.yaml文件的开源 AISIX 网关。
- AISIX Cloud 环境,以及具有
- 向 Agent 签发 JWT Token 的系统,以及与其签名方式相应的验证材料:
- 使用 JWKS 验证时,请准备预期的签发者,以及其 JWKS 端点 URL 或 OIDC 发现文档(
<issuer>/.well-known/openid-configuration)。 - 使用 HMAC 签名时,请准备共享密钥。其 UTF-8 编码长度必须至少为 32 字节;预期的签发者和受众可选。
- 使用 JWKS 验证时,请准备预期的签发者,以及其 JWKS 端点 URL 或 OIDC 发现文档(
- 调用方可以使用的模型别名;AISIX Cloud 工作流还需要其模型 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 Cloud 和开源 AISIX 网关采用相同的信任设置,但二者对签发者唯一性的约束方式不同:
| 字段 | 说明 |
|---|---|
issuer | 预期的 iss 声明,会与 Token 进行精确比较。已配置的签发者在 AISIX Cloud 环境中必须唯一;在资源文件中,设置了签发者的已启用服务提供方必须使用不同的值。 使用 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 指定一项声明,Key 中的点用于遍历嵌套对象。字符串声明必须等于一个预期值,数组声明必须包含一个预期值。 |
leeway_secs | 基于时间的声明所允许的时钟偏差,范围为 0 到 300 秒。默认 0。 |
enabled | 服务提供方是否参与认证。默认 true。 |
对于 JWKS 服务提供方,省略 jwks_uri 时,AISIX 会从签发者的发现文档解析并缓存签名 Key 端点。如果网关无法访问发现文档,请显式提供 jwks_uri。
AISIX Cloud
导出基础 URL、Admin Token、环境 ID 和模型 ID:
# AISIX_CP 是 Admin API 基础 URL;应包含 /api,且不含尾部斜杠
# 本地私有化部署快速入门使用 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 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 Cloud 中,每个身份还会继承该 Key 的预算。Agent 使用自己的 JWT 认证,因此无须分发 Key 的明文值。
开源 AISIX 网关
对于开源 AISIX 网关,请在 resources.yaml 中声明 OIDC 服务提供方和绑定 JWT 的调用方 API Key。allowed_models 中的模型别名也必须在文件中定义:
_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 Token 认证。请为网关进程设置两个变量,并且不要把 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 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 条目中通过环境变量提供密钥,使明文不出现在文件里:
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 Cloud 会以 422 和错误码 DP_INCOMPATIBLE 拒绝保存。请先升级该环境中的网关。
认证请求
让 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.code | HTTP 状态 | 含义 |
|---|---|---|
jwt_expired | 401 | Token 的 exp 截止时间已过,请获取新 Token。 |
jwt_invalid | 401 | Token 格式错误,或未通过签发者、签名、签名算法、受众、必需声明或生效时间验证。 |
jwt_claims_rejected | 403 | Token 有效,但不满足服务提供方的 required_scopes 或 bound_claims。 |
jwt_identity_unmapped | 401 | 配置的身份声明缺失或不是字符串,或者该身份无法解析到任何 Key——没有调用方 API Key 的 jwt_provider 和 jwt_subject 与之匹配,也没有 Claim 映射命中。请检查 Token 声明、Key 绑定和映射。 |
jwks_unavailable | 503 | AISIX 无法解析或获取服务提供方的签名 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 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 仍可使用明文值认证,之后也可以重新关联到新的服务提供方。