JWT 认证
AISIX 可以使用 OpenID Connect(OIDC)身份服务提供方签发的短期 JSON Web Token(JWT)凭证认证 Agent,无须使用长期调用方 API Key。每个经过验证的外部身份都会映射到调用方 API Key,并继承该 Key 的模型访问权限和限流。在 AISIX Cloud 中,映射后的 Key 还会携带预算和用量归因。
支持的服务提供方包括 Keycloak、Entra ID、Okta、Auth0,以及使用受支持算法签署 JWT Token 的所有 OIDC 兼容服务提供方。AISIX 会为每个请求验证 Token 签名和声明,Agent 不需要调用方 API Key 的明文值。
面向人工运维人员的控制台单点登录和面向 Agent 请求的网关 JWT 认证彼此独立,配置其中一项不会影响另一项。
工作原理
当环境中至少存在一个已启用的 OIDC 服务提供方时,AISIX 会检查每个请求的 Bearer Token:
- 如果 Bearer 是 JWT,其
iss(签发者)声明会选择匹配的信任服务提供方。签发者与所有已启用服务提供方均不匹配 的 Token 会被拒绝。 - AISIX 使用服务提供方的 JSON Web Key Set(JWKS)验证 Token 签名,并验证注册声明:始终必需的
exp(过期时间)、与服务提供方接受受众匹配的aud(受众),以及存在时的nbf(生效时间)。 - 执行服务提供方的
required_scopes和bound_claims要求。 - 服务提供方身份声明的值(默认为
sub)会选择jwt_subject与该值相等,且jwt_provider指向此服务提供方的调用方 API Key。随后请求会以此 Key 的身份运行。将绑定限定到服务提供方,可以防止第二个受信任服务提供方签发冒充此服务提供方身份的 Token。
未通过验证或无法映射到调用方 API Key 的 Token 会在请求到达服务提供方、MCP 服务器或向量存储前被 AISIX 拒绝。身份服务提供方的签名 Key 轮换会自动生效,无须重启网关。
前置条件
开始前,请准备以下内容:
- 以下任一配置路径:
- AISIX Cloud 环境,以及具有
write作用域的 Admin Token。对于本地部署,请先完成 AISIX Cloud 快速入门;如需申请混合云访问权限,请联系 API7。 - 加载声明式
resources.yaml文件的开源 AISIX 网关。
- AISIX Cloud 环境,以及具有
- 向 Agent 签发 JWT Token 的 OIDC 身份服务提供方及其签发者 URL。你还需要其 JWKS 端点 URL 或 OIDC 发现文档(
<issuer>/.well-known/openid-configuration)。 - 调用方可以使用的模型别名;AISIX Cloud 工作流还需要其模型 ID。如果尚未创建,请先配置服务提供方密钥和模型别名。
curl和jq。开源网关还需要 OpenSSL,以运行下文的凭证生成命令。
服务提供方必须使用 AISIX 支持的非对称算法签署 Token:RSA(RS256、RS384、RS512、PS256、PS384 或 PS512)、ECDSA(ES256 或 ES384),或 EdDSA。HMAC 签名的 JWT Token 会被拒绝。
以下章节先演示 AISIX Cloud Admin API 工作流。对于开源网关,请参见开源网关配置。
导出基础 URL、Admin Token、环境 ID 和模型 ID:
export AISIX_CP="http://localhost:8080/api"
export AISIX_TOKEN="YOUR_ADMIN_TOKEN"
export ENV_ID="YOUR_ENVIRONMENT_ID"
export MODEL_ID="YOUR_MODEL_ID"
注册信任服务提供方
注册 AISIX 应信任的身份服务提供方。至少需要提供签发者和接受的受众:
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"
}
}
服务提供方字段
| 字段 | 说明 |
|---|---|
issuer | 预期的 iss 声明,会与 Token 进行精确比较,并且在环境中唯一。 |
audiences | 接受的 aud 值。Token 的受众必须至少包含其中一个;没有受众声明的 Token 会被拒绝。 |
jwks_uri | 获取签名 Key 的端点。省略时,从签发者的 OIDC 发现文档解析。 |
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_uri 时,AISIX 会从签发者的发现文档解析并缓存签名 Key 端点。如果网关无法访问发现文档,请显式提供 jwks_uri。
将调用方 API Key 绑定到身份
创建或更新调用方 API Key,并同时设置以下两个字段:
jwt_subject:已验证 Token 映射到的外部身份。将它设为身份服务提供方在其identity_claim所指定声明中写入的值。jwt_provider:允许声明该主体的 OIDC 服务提供方名称。只有此服务提供方签发的 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,使按身份设置的模型访问权限、限流、预算和用量归因彼此独立。Agent 使用自己的 JWT 认证,因此无须分发 Key 的明文值。
开源网关配置
对于开源网关,请在 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 请求。
认证请求
让 Agent 从身份服务提供方获取 Token。设置模型别名和 Token,然后像使用调用方 API Key 一样,在代理 API 上发送该 Token:
export MODEL_ALIAS="YOUR_MODEL_ALIAS"
export AGENT_JWT="eyJhbGciOiJSUzI1NiIsImtpZCI6..."
curl -sS -X POST "http://127.0.0.1:3000/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 声明。
拒绝原因
Token 被拒绝时,错误响应会携带稳定的 error.code,客户端无须解析消息即可处理:
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 | 配置的身份声明缺失或不是字符串,或者没有调用方 API Key 的 jwt_provider 和 jwt_subject 与之匹配。请检查 Token 声明和 Key 绑定。 |
jwks_unavailable | 503 | 无法获取服务提供方签名 Key。请在身份服务提供方恢复后重试。 |
Key 轮换
身份服务提供方引入新签名 Key 时,AISIX 会在遇到无法识别的 Key ID 后刷新缓存的 Key 集合。刷新频率限制为每秒一次,因此紧接在另一次刷新后的请求可能需要重试。无须更改配置或重启网关。
AISIX 将缓存的 JWKS 视为 10 分钟内有效。超过该间隔后,下一次认证请求会触发刷新。刷新后的集合不再包含已退役 Key 后,由该 Key 签名的 Token 将无法认证。如果刷新时 JWKS 端点不可用,AISIX 会继续使用上次成功获取的 Key 集合。现有认证可以继续,但退役 Key 仍受信任,直到后续刷新成功。
禁用或删除信 任服务提供方
禁用服务提供方可在保留配置的同时停止信任其 Token:
export PROVIDER_ID="b2c3d4e5-6789-4abc-def0-123456789abc"
curl -sS -X PATCH "$AISIX_CP/environments/$ENV_ID/oidc_providers/$PROVIDER_ID" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{"enabled": false}' | jq
删除服务提供方会彻底移除信任:
curl -sS -X DELETE "$AISIX_CP/environments/$ENV_ID/oidc_providers/$PROVIDER_ID" \
-H "Authorization: Bearer $AISIX_TOKEN" | jq
删除服务提供方不会影响调用方 API Key 或其 jwt_subject 绑定。这些 Key 仍可使用明文值认证,之后也可以重新关联到新的服务提供方。