API7 网关 AI Agent Skill:openid-connect 插件
概览
openid-connect 插件将 API7 企业版与外部 OpenID Connect(OIDC)身份提供方(Keycloak、Auth0、Okta 等)集成。它支持面向浏览器应用的完整授权码流程、面向 API 客户端的 Bearer 令牌校验,以及令牌内省或本地 JWKS 校验。
适用场景
- 与企业身份提供方集成,例如 Keycloak、Auth0、Okta、Azure AD
- 基于浏览器的授权码流程 SSO
- 使用 Bearer 令牌保护 API
- 跨多个路由集中身份认证
插件配置参考(路由/服务)
必填字段
| 字段 | 类型 | 是否必填 | 默认值 | 说明 |
|---|---|---|---|---|
client_id | string | 是 | — | OAuth 2.0 客户端 ID |
client_secret | string | 是 | — | OAuth 2.0 客户端密钥,在数据库中加密存储 |
discovery | string | 是 | — | OIDC 发现 URL |
身份认证与 Scope
| 字段 | 类型 | 是否必填 | 默认值 | 说明 |
|---|---|---|---|---|
scope | string | 否 | "openid" | 以空格分隔的 OIDC Scope |
bearer_only | boolean | 否 | false | 仅要求 Bearer 访问令牌,不进行重定向 |
required_scopes | array | 否 | — | 访问令牌中必须包含的 Scope |
realm | string | 否 | "apisix" | WWW-Authenticate 响应头中的 Realm |
URI 与重定向
| 字段 | 类型 | 是否必填 | 默认值 | 说明 |
|---|---|---|---|---|
redirect_uri | string | 否 | {route_uri}/.apisix/redirect | 身份认证后的重定向 URI |
logout_path | string | 否 | "/logout" | 触发退出登录的路径 |
post_logout_redirect_uri | string | 否 | — | 退出登录后的重定向 URL |
unauth_action | string | 否 | "auth" | 未通过身份认证时的操作:"auth"(重定向)、"deny"(401)、"pass"(允许) |
令牌校验
| 字段 | 类型 | 是否必填 | 默认值 | 说明 |
|---|---|---|---|---|
introspection_endpoint | string | 否 | — | 令牌内省端点 URL |
public_key | string | 否 | — | 用于本地 JWT 校验的 PEM 公钥 |
use_jwks | boolean | 否 | false | 使用发现文档中的 JWKS 进行本地 JWT 校验 |
token_signing_alg_values_expected | string | 否 | — | 预期的 JWT 签名算法 |
会话管理
| 字段 | 类型 | 是否必填 | 默认值 | 说明 |
|---|---|---|---|---|
session.secret | string | 是* | — | 用于会话加密的至少 16 个字符的密钥,授权码流程必须配置 |
session.cookie.lifetime | integer | 否 | 3600 | 会话 Cookie 有效期,单位为秒 |
session.storage | string | 否 | "cookie" | 可选 "cookie" 或 "redis" |
转发到上游的请求头
| 字段 | 类型 | 是否必填 | 默认值 | 说明 |
|---|---|---|---|---|
set_access_token_header | boolean | 否 | true | 设置 X-Access-Token 请求头 |
access_token_in_authorization_header | boolean | 否 | false | 在 Authorization 请求头中设置令牌 |
set_id_token_header | boolean | 否 | true | 设置 X-ID-Token 请求头 |
set_userinfo_header | boolean | 否 | true | 设置 X-Userinfo 请求头 |
hide_credentials | boolean | 否 | false | 转发到上游前移除身份认证请求头 |
高级配置
| 字段 | 类型 | 是否必填 | 默认值 | 说明 |
|---|---|---|---|---|
ssl_verify | boolean | 否 | false | 校验 IdP 的 SSL 证书 |
timeout | integer | 否 | 3 | 向 IdP 发出请求的超时时间,单位为秒 |
use_pkce | boolean | 否 | false | 启用 PKCE(RFC 7636) |
renew_access_token_on_expiry | boolean | 否 | true | 自动刷新即将过期的令牌 |
令牌校验模式
1. 令牌内省(bearer_only 的默认模式)
API7 企业版会为每个请求调用 IdP 的内省端点。
- 优点:实时校验,可处理令牌撤销
- 缺点:增加延迟(需要网络调用 IdP)
{
"openid-connect": {
"client_id": "my-app",
"client_secret": "secret",
"discovery": "https://keycloak.example.com/realms/my/.well-known/openid-configuration",
"bearer_only": true,
"introspection_endpoint": "https://keycloak.example.com/realms/my/protocol/openid-connect/token/introspect"
}
}
2. 本地 JWKS 校验
API7 企业版会从发现文档中获取 JWKS,并在本地校验 JWT。
- 优点:速度快(无需每个请求都调用 IdP),可扩展性好
- 缺点:在 JWKS 缓存刷新前无法检测已撤销的令牌
{
"openid-connect": {
"client_id": "my-app",
"client_secret": "secret",
"discovery": "https://keycloak.example.com/realms/my/.well-known/openid-configuration",
"bearer_only": true,
"use_jwks": true
}
}
3. 静态公钥校验
直接提供公钥。无需发现流程或内省调用。
{
"openid-connect": {
"client_id": "my-app",
"client_secret": "secret",
"discovery": "https://keycloak.example.com/realms/my/.well-known/openid-configuration",
"bearer_only": true,
"public_key": "-----BEGIN PUBLIC KEY-----\nMIIBIjAN...\n-----END PUBLIC KEY-----"
}
}
分步操作:授权码流程(Keycloak)
1. 创建启用 openid-connect 的路由
a7 route create -g default -f - <<'EOF'
{
"id": "oidc-webapp",
"uri": "/app/*",
"plugins": {
"openid-connect": {
"client_id": "apisix-client",
"client_secret": "your-client-secret",
"discovery": "https://keycloak.example.com/realms/myrealm/.well-known/openid-configuration",
"scope": "openid email profile",
"redirect_uri": "http://127.0.0.1:9080/app/redirect",
"session": {
"secret": "my-16-char-secret"
}
}
},
"upstream": {
"type": "roundrobin",
"nodes": [{"host": "webapp", "port": 3000, "weight": 1}]
}
}
EOF
2. 流程
- 用户访问
http://127.0.0.1:9080/app/dashboard,此时没有会话 - API7 企业版将用户重定向到 Keycloak 登录页。
- 用户完成身份认证后,Keycloak 重定向到
http://127.0.0.1:9080/app/redirect?code=... - API7 企业版使用授权码换取令牌,并将其存储到会话 Cookie 中。
- 后续请求会自动使用会话 Cookie
分步操作:Bearer 令牌 API 保护
1. 创建用于 API 保护的路由
a7 route create -g default -f - <<'EOF'
{
"id": "oidc-api",
"uri": "/api/*",
"plugins": {
"openid-connect": {
"client_id": "apisix-client",
"client_secret": "your-client-secret",
"discovery": "https://keycloak.example.com/realms/myrealm/.well-known/openid-configuration",
"bearer_only": true,
"use_jwks": true
}
},
"upstream": {
"type": "roundrobin",
"nodes": [{"host": "backend", "port": 8080, "weight": 1}]
}
}
EOF
2. 获取并使用令牌
# 从 IdP 获取令牌
TOKEN=$(curl -s -X POST \
"https://keycloak.example.com/realms/myrealm/protocol/openid-connect/token" \
-d "client_id=apisix-client" \
-d "client_secret=your-client-secret" \
-d "grant_type=client_credentials" \
| jq -r '.access_token')
# 调用 API
curl -i http://127.0.0.1:9080/api/resource \
-H "Authorization: Bearer ${TOKEN}"
提供方发现 URL
| 提供方 | 发现 URL 模式 |
|---|---|
| Keycloak | https://{host}/realms/{realm}/.well-known/openid-configuration |
| Auth0 | https://{tenant}.auth0.com/.well-known/openid-configuration |
| Okta | https://{org}.okta.com/.well-known/openid-configuration |
| Azure AD | https://login.microsoftonline.com/{tenant}/v2.0/.well-known/openid-configuration |
https://accounts.google.com/.well-known/openid-configuration |