跳到主要内容
版本:3.9.x

将外部认证的用户信息转发到上游

在使用 OpenID ConnectSAML Auth 等认证插件时,你可能需要将经过身份验证的用户信息传递给上游服务。这使上游应用程序能够基于用户身份实现额外的业务逻辑,例如个性化、审计和访问控制。

本指南以 Azure AD (Microsoft Entra ID) 作为示例身份提供商。

本指南涵盖了两种解决方案:

  1. 将消费者名称与外部身份验证关联:将解析后的用户标识符(例如,subname_id)设置为当前请求的 consumer_name
  2. 将用户信息请求头转发到上游:通过自定义请求头将解析后的用户信息传递给上游服务。

前置条件

  1. 安装 API7 企业版
  2. 在网关组上运行 API

创建路由

在 API7 控制板中为你想要保护的上游服务创建一个路由。

创建路由

将消费者名称与外部身份验证关联

身份验证成功后,openid-connectsaml-auth 都会将用户信息存储在 ctx.external_user 中。配置 serverless-post-function 使其在 rewrite 阶段运行,并将其放置在路由上的认证插件之后,以便 ctx.external_user 已被填充。

使用 OpenID Connect

配置 OpenID Connect 插件

登录到 Azure 门户,转到 App registrations 服务并注册一个新应用程序。

azure-ad-create-an-app

在 IdP 和插件中配置重定向 URI:

配置 OpenID Connect 重定向 URL

将 token 版本设置为 v2:

将 token 版本设置为 v2

从 IdP 复制客户端信息(如 client_idclient_secret):

复制 OpenID Connect 客户端信息

复制 OpenID Connect 客户端 secret

在路由上配置 openid-connect 插件。请将高亮的配置替换为你自己的值:

openid-connect
bearer_only: false
client_id: de90e86d-d632-4861-99cf-4a97fb2482fe
client_secret: Jex8Q~O.EwzJUQrwL.ji4eK4zCSgpmc4LZtLBbR1
discovery: https://login.microsoftonline.com/a7a70f5e-0b17-4a67-90ab-9e85ff6d9f59/v2.0/.well-known/openid-configuration
redirect_uri: https://your-gateway.com/anything/callback
required_scopes:
- openid
scope: openid email profile
session:
secret: f86cf31663a9c9fa0a28c2cc78badef1

配置 OpenID Connect 插件

使用 serverless-post-function 设置 consumer_name

使用 ctx.external_user 中解析的 sub 来设置请求的 consumer_name

serverless-post-function
phase: rewrite
functions:
- |
return function(conf, ctx)
local core = require("apisix.core")
core.log.warn(
"ctx.external_user: ",
core.json.encode(ctx.external_user, true)
)
if type(ctx.external_user) == "table" and ctx.external_user.sub then
ctx.consumer_name = ctx.external_user.sub
core.log.warn("consumer_name: ", ctx.consumer_name)
end
end

配置 serverless-post-function 以设置 consumer_name

验证

在浏览器中访问路由以完成 OpenID Connect 身份验证:

访问路由进行 OpenID Connect 身份验证

检查网关访问日志以验证 consumer_name 已被设置:

检查访问日志中的 consumer_name

使用 SAML Auth

配置 SAML Auth 插件

登录到 Azure 门户,转到 Enterprise applications 服务并创建一个新的 SAML 应用程序。

创建一个新的 SAML 应用程序

在 IdP 中配置 SAML 应用程序:

为 SAML 设置 Azure AD 应用程序信息

复制 IdP 元数据和证书信息:

复制 SAML IdP 信息

在路由上配置 saml-auth 插件。请将高亮的配置替换为你自己的值:

saml-auth
auth_protocol_binding_method: HTTP-POST
idp_cert: |-
-----BEGIN CERTIFICATE-----
MIIC8DCCAdigAwIBAgIQFP0SV5NUxJxBB6125kRy4zANBgkqhkiG9w0BAQsFADA0MTIwMAYDVQQD
EylNaWNyb3NvZnQgQXp1cmUgRmVkZXJhdGVkIFNTTyBDZXJ0aWZpY2F0ZTAeFw0yNjAxMTkwNjQ2
MDRaFw0yOTAxMTkwNjQ2MDRaMDQxMjAwBgNVBAMTKU1pY3Jvc29mdCBBenVyZSBGZWRlcmF0ZWQg
U1NPIENlcnRpZmljYXRlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvWTXi5qeU2oH
...
io9oACxmTrSUJWyGQbPZtrwGUQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQCAKT5abG4qxLpEraNU
-----END CERTIFICATE-----

idp_uri: https://login.microsoftonline.com/a7a70f5e-0b17-4a67-90ab-9e85ff6d9f59/saml2
login_callback_uri: /anything/login_callback
logout_callback_uri: /anything/logout_callback
logout_redirect_uri: /anything/logout_ok
logout_uri: /anything/logout
secret: testsecret
sp_cert: |-
-----BEGIN CERTIFICATE-----
MIIDDzCCAfegAwIBAgIUcULAtArasoM/knVgg/RYEaJDq+IwDQYJKoZIhvcNAQEL
...
5V60djI2y+XTkvDCz/o/1YftMw==
-----END CERTIFICATE-----
sp_issuer: api7
sp_private_key: |-
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDiVOfSpH5xTz8d
...
IwBDUu3iS4CcCX18UwwiSjE=
-----END PRIVATE KEY-----

配置 SAML Auth 插件

使用 serverless-post-function 设置 consumer_name

使用 ctx.external_user 中解析的 name_id 来设置请求的 consumer_name

serverless-post-function
phase: rewrite
functions:
- |
return function(conf, ctx)
local core = require("apisix.core")
core.log.warn(
"ctx.external_user: ",
core.json.encode(ctx.external_user, true)
)
if type(ctx.external_user) == "table" and ctx.external_user.name_id then
ctx.consumer_name = ctx.external_user.name_id
core.log.warn("consumer_name: ", ctx.consumer_name)
end
end

配置 serverless-post-function 以为 SAML 设置 consumer_name

验证

在浏览器中访问路由以完成 SAML 身份验证:

访问路由进行 SAML 身份验证

检查网关访问日志以验证 consumer_name 已被设置:

检查 SAML 访问日志中的 consumer_name

将用户信息请求头转发到上游

使用 OpenID Connect

openid-connect 插件内置支持将用户信息转发到上游服务。不需要为 OpenID Connect 用户信息转发提供额外的 serverless-post-function 配置。

将 OpenID Connect 用户信息传递给上游

使用 SAML Auth

使用 serverless-post-functionctx.external_user 中提取用户信息并设置自定义请求头。

serverless-post-function
phase: rewrite
functions:
- |
return function(conf, ctx)
local core = require('apisix.core')
local user = ctx.external_user
if user and user.authenticated then
core.request.set_header('X-SAML-NameID', user.name_id or '')
-- 设置完整的用户信息请求头
-- (Base64 编码的 JSON)
local userinfo = {
-- 用户名称 ID
name_id = user.name_id,
-- 会话索引
session_index = user.session_index,
-- IdP 发行者
issuer = user.issuer,
-- IdP 用户属性
attrs = user.attrs
}
core.request.set_header(
'X-SAML-Userinfo',
ngx.encode_base64(core.json.encode(userinfo))
)
end
end

配置 serverless-post-function 将用户信息传递给上游

验证

使用 SAML 身份提供商进行身份验证后,向路由发送请求。上游服务应接收到类似于以下的请求头:

X-SAML-NameID: xxxx
X-SAML-Userinfo: xxxx

验证 SAML 用户信息请求头

附加资源