单点登录(SAML)
单点登录(SSO)让 AISIX Cloud 组织的成员通 过你的身份提供方(IdP)登录控制台,而不必使用密码。每个组织配置自己的 SAML 2.0 连接,因此可以对接 Microsoft Entra ID、Okta、Keycloak 或其他任何标准 SAML 身份提供方。本页介绍适用于所有身份提供方的配置和行为。使用 Microsoft Entra ID 的分步配置请参见集成 Microsoft Entra ID。
SaaS 服务和 On-Premises 部署都提供 SSO,且不受套餐限制。SSO 在控制台的 设置 页面中,通过 单点登录(SAML) 卡片配置。
一个连接可以:
- 让现有成员通过身份提供方登录;
- 在新成员首次登录时将其加入组织(JIT 预配);
- 根据身份提供方发送的属性设置成员角色;
- 要求 Owner 以外的成员必须通过 SSO 访问组织。
SSO 与 SCIM 目录同步互为补充:SCIM 预先创建、更新和停用成员,SSO 负责这些成员如何登录。两者也可以单独使用。
AISIX Cloud 账号属于个人而不属于组织:同一个账号可以是多个组织的成员。因此,只有当账号已与此人在身份提供方中的身份关联后,SSO 才会登录到该账号。在 On-Premises 控制面上,首次登录时按邮箱地址建立关联。在 SaaS 服务上,由本人在关联页面确认,除非邮箱地址位于组织的某个已验证域名内。参见登录如何找到账号。
谁可以配置 SSO
只有组织 Owner 可以创建、修改或移除 SSO 连接。Admin 只能只读查看该卡片,其他角色(包括自定义角色)看不到它。
这样设计是有意为之:掌控组织所信任的身份提供方的人,可以以组织内任意成员(包括 Owner)的身份登录。因此选择哪个身份提供方,是 Owner 才能做的决定。
服务提供方信息
单点登录(SAML) 卡片顶部列出需要在身份提供方中登记的信息。这些值由控制面的公开 URL 和组织 ID 生成:
| 字段 | 格式 | Entra ID 字段 |
|---|---|---|
| 实体 ID(标识符) | <public-base-url>/api/auth/sso/saml/<org-id>/metadata | Identifier (Entity ID) |
| 断言消费服务 URL(回复 URL) | <public-base-url>/api/auth/sso/saml/<org-id>/acs | Reply URL (Assertion Consumer Service URL) |
| 登录 URL | <public-base-url>/login?sso=<org-slug> | Sign on URL |
实体 ID 同时也是服务提供方元数据文档的 URL。该文档是公开的,支持导入 SP 元数据的身份提供方可以直接读取;下载服务提供商元数据 保存的也是同一份文档。元数据声明了一个 HTTP-POST 断言消费服务、不签名的认证请求,以及要求签名的断言。
实体 ID 和回复 URL 使用组织 ID 而不是组织 slug,因此即使 slug 改变,身份提供方中的登记也仍然有效。登录 URL 使用 slug。
在 On-Premises 控制面上,<public-base-url> 即 AISIX_CLOUD_PUBLIC_BASE_URL 的值,在 Helm Chart 中为 api.publicBaseURL。它必须是浏览器访问控制面实际使用的 URL,因为身份提供方会把浏览器送回这个地址。参见运行时 URL。
配置身份提供方
对于 Microsoft Entra ID,请按照分步指南集成 Microsoft Entra ID 操作。对于其他 SAML 2.0 身份提供方,配置包含相同的几个部分:
- 在身份提供方中登记 AISIX Cloud。 创建一个 SAML 应用,填入 SSO 卡片中的实体 ID、断言消费服务 URL,以及登录 URL(如果身份提供方有对应字段)。支持导入服务提供方元数据的身份提供方,也可以直接从实体 ID URL 读取。
- 发送稳定的名称标识符。 AISIX Cloud 按断言中的名称标识符(NameID)识别再次登录的人,因此 NameID 必须是稳定的个人标识,不随邮箱地址或用户名变化,例如不可变的用户 ID。对于 Microsoft Entra ID,请使用
user.objectid,格式为 Persistent。transient 格式的 NameID 每次登录都会变化,会被拒绝并返回SSO_NAME_ID_TRANSIENT;没有 NameID 的断言会被拒绝并返回SSO_NAME_ID_MISSING。请在成员开始登录之前确定 NameID,参见之后更改 NameID。 - 发送邮箱地址。 在 邮箱属 性 指定的属性中发送每个人的邮箱地址。同时发送显示名称;如果使用角色映射规则,还要发送规则读取的属性。
- 签名,不加密。 身份提供方必须对响应或断言签名,且不能加密断言。
- 授予访问权限。 如果身份提供方要求,把需要登录的人员分配到该应用。
- 将身份提供方元数据导入 AISIX Cloud。 在 SSO 卡片上,将身份提供方的元数据粘贴到 身份提供商元数据 XML 中并选择 读取元数据,或选择 上传元数据文件。检查 身份提供商实体 ID、单点登录 URL 和 签名证书,然后开启 启用单点登录,按照连接设置选择其他选项,再选择 保存。
AISIX Cloud 从元数据中读取身份提供方的实体 ID、HTTP-Redirect 登录端点和签名证书。它不会从 URL 下载元数据,因此请粘贴或上传元数据文档本身。也可以不用元数据,手动填写这三个字段。
然后通过登录 URL 登录以测试连接。
轮换签名证书
一个连接最多保存 10 个签名证书,由其中任一证书签名的响应都会被接受。每个证书可以以 PEM 格式粘贴,也可以以 base64 编码的 DER 格式(即元数据文档和身份提供方控制台显示的格式)粘贴。
要在不中断登录的情况下轮换身份提供方的证书:
- 在身份提供方中创建新证书,但暂不用它签名。
- 在 SSO 卡片中选择 添加证书,粘贴新证书后保存。
- 让身份提供方改用新证书签名。
- 确认使用新证书可以正常登录后,从 SSO 卡片中移除旧证书并保存。
- 重新开启强制单点登录。
添加或移除证书都会自动关闭 强制单点登录,这就是要在最后才重新开启它的原因。如果身份提供方使用 SSO 卡片中没有的证书签名,所有登录都会以 SSO_RESPONSE_INVALID 失败。Entra ID 中的具体步骤参见 Entra ID 指南中的轮换签名证书。
连接设置
| 设置 | 默认值 | 说明 |
|---|---|---|
| 启用单点登录 | 关闭 | 成员可以通过身份提供方登录。配置过程中可以先保存一个未启用的连接。 |
| 登录时自动添加新成员(JIT) | 关闭 | 组织尚不认识的人首次登录时自动成为成员。参见成员如何加入。 |
| 默认角色 | member | 登录时新加入成员的角色;存在角色映射规则但没有规则命中时,也使用该角色。可以是 member、admin 或自定义角色,不能是 owner。 |
| 邮箱属性 | http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress | 携带邮箱地址的断言属性。留空使用默认值。 |
| 显示名称属性 | http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name | 携带显示名称的断言属性。留空使用默认值。 |
| 身份提供商实体 ID、单点登录 URL、签名证书 | 无 | 连接所信任的身份提供方,通常从其元数据中填写。单点登录 URL 是身份提供方的 HTTP-Redirect 端点。 |
| 角色映射 | 无规则 | 按顺序根据身份提供方属性设置成员角色的规则。参见将身份提供方属性映射为角色。 |
| 强制单点登录 | 关闭 | Owner 以外的成员只能通过 SSO 访问组织。参见强制单点登录。 |
属性按 Name 或 FriendlyName 匹配,不区分大小写。断言中缺少邮箱属性时,如果 NameID 是邮箱格式,就把它用作邮箱地址;否则断言中没有邮箱地址。这样的登录对身份已关联账号的人照常有效,首次登录则进入关联页面。缺少显示名称属性时,使用名和姓拼接;名和姓也没有时,使用邮箱地址;没有邮箱地址时,使用 NameID。
移除连接 会删除该连接。成员将无法再通过身份提供方登录,已通过它打开的会话会持续到过期为止。
配置变更会以资源类型 sso_connection 记录在审计日志中;SSO 添加成员或修改成员角色时,会记录为 member 变更。身份与账号 之间的关联也会被记录,参见身份关联。
通过 SSO 登录
登录页面提供的 SSO 入口取决于部署方式:
- On-Premises。 登录页面从不要求输入组织标识。当组织有已启用的 SSO 连接时,页面会显示以组织名称命名的 使用
<组织>的 SSO 登录 按钮,点击后直接跳转到身份提供方。没有已启用的连接时,页面上完全没有 SSO 入口。 - SaaS。 成员选择 使用 SSO 登录,输入组织标识(即登录 URL 末尾的 slug),随后被带到身份提供方。
在身份提供方登录后,成员即进入该组织;如果其身份尚未关联账号,首次登录会进入关联页面。两种部署方式下,登录页面都会保留密码登录表单,即使开启了强制单点登录也是如此,因为 Owner 始终可以使用密码登录。
登录 URL /login?sso=<org-slug> 在两种部署方式下都可用,它打开的页面只有该组织的 使用 SSO 登录 按钮。可以把它分享给成员,或在身份提供方中登记为登录 URL,使身份提供方的应用启动入口(例如 Entra ID 的 My Apps 磁贴)指向该页面。成员随后在该页面上选择 使用 SSO 登录。
从 1.5.x 或更早版本升级、仍包含多个组织的 On-Premises 控制面,在这些组织合并为一个之前不会显示 SSO 按钮。
登录必须在发起它的浏 览器中、在 10 分钟内完成。找到此人账号的登录会替换该浏览器原有的会话;进入关联页面的登录则保留浏览器原有的会话。
以下功能不受支持:
- 身份提供方发起的登录。 AISIX Cloud 会拒绝不对应其自身发起登录的 SAML 响应。
- 单点登出。 退出控制台只结束 AISIX Cloud 会话,身份提供方的会话仍然保留。
- 加密断言。 身份提供方必须对响应或断言签名,且不能加密断言。
登录如何找到账号
身份关联
某个身份首次登录时,AISIX Cloud 会把该连接及该身份的 NameID 关联到一个账号。之后的每次登录都只通过这个关联找到账号,不再参考断言中的邮箱地址,因此即使此人在身份提供方中的邮箱地址发生变化,仍会登录到同一个账号。一个连接中,每个 NameID 只关联一个账号,每个账号也只关联一个 NameID。
以下情况会删除关联:
- 此人被移出组织,无论是在控制台中、通过 SCIM,还是其他任何方式;
- 连接被移除;
- 身份提供商实体 ID 发生变化,这会删除该连接的所有关联。
修改身份提供方的单点登录 URL 或证书不会影响关联。
关联以资源类型 sso_identity_link 记录在审计日志中:建立关联时记录 create,via 为 connect、trusted_email 或 email_claim;因账号已关联另一个 NameID 而拒绝关联时记录 reject;因已验证域名接管未验证账号而删除关联时记录 delete。接管本身以资源类型 verified_domain_claim 记录,参见审计记录。关联页面发出的邮箱验证链接以资源类型 sso_email_claim 记录:发送链接时记录 create,使用链接时记录 complete。审计记录中从不包含任何令牌。
首次登录
还没有关联时,结果取决于 AISIX Cloud 是否信任身份提供方断言的邮箱地址:
- 在 On-Premises 控制面上,身份提供方由运维方自己掌控,信任所有地址。
- 在 SaaS 服务上,每个组织都掌控自己的身份提供方,它可以断言任何人的地址。只有组织已验证域名内的地址才被信任,按域名精确匹配,不包括子域名。
地址受信任时,登录会关联使用该地址的账号(不区分大小写)。没有账号使用该地址时,只有在组织会接纳此人(已开启 JIT 预配,或此人有待接受的邀请)时,才会创建一个没有密码的账号;否则登录被拒绝并返回 SSO_NOT_A_MEMBER,也不会创建账号。此人直 接进入组织,不经过关联页面。
在 SaaS 服务上,使用受信任地址却从未验证过邮箱的账号,是由没有证明自己拥有该地址的人注册的。登录会接管这个账号:账号失去密码、会话、尚未使用的邮箱验证链接,以及与其他组织 SSO 连接的关联。账号名称改为断言中的显示名称,即 JIT 预配新建账号时会使用的名称;账号对《用户协议》和《隐私政策》的同意记录被清除,邮箱地址被标记为已验证。接管会记录为一条 verified_domain_claim 审计记录,参见组织域名。已验证过邮箱的账号会直接关联,不会被接管,并保留原名称。在 On-Premises 控制面上不会接管任何账号:账号保留名称、密码和会话。
其他情况,即 SaaS 服务上已验证域名以外的地址,以及两种部署方式下没有邮箱地址的断言,此人会进入关联页面。
关联页面
关联页面 /sso-connect 会说明此人已通过组织的 SSO 以哪个邮箱地址完成认证,但该身份尚未关联任何账号。该身份在完成登录的浏览器中等待 10 分钟。在本人确认之前,不会建立任何关联。页面提供以下几种方式:
- 登录已有账号。 使用任意账号的密码登录,然后确认关联。浏览器已登录时,页面会针对当前账号提供 关联到
<email>,以及 使用其他账号。在 SaaS 服务上,与所有密码登录一样,账号的邮箱地址必须已经验证。 - 创建新账号。 邮箱地址固定为身份提供方发送的地址,不能修改。此人像新注册账号一样验证该地址。从验证链接登录后,浏览器会回到该组织的 SSO 登录页面,此人再次通过 SSO 登录并确认关联。断言中没有邮箱地址、该地址属于没有密码的账号,或部署只允许通过邀请创建账号(On-Premises 控制面即是如此)时,不提供此选项。
- 发送验证链接。 如果断言中的邮箱地址属于一个没有密码的现有账号(例如通过 SCIM 预配的账号,或在 On-Premises 控制面上由管理员创建的账号),页面会提供 向
<email>发送验证链接,而不是创建新账号。链接一小时内有效,只能使用一次,发出新链接后旧链接失效。链接不依赖浏览器,可以在任何地方打开。打开后的页面会写明组织的名称和标识以及账号,选择 关联并登录 即关联该身份、把邮箱地址标记为已验证并登录。之后账号仍然没有密码。如果浏览器当前登录的是另一个账号,页面会说明关联后将退出该账号。
有密码的账号只能通过登录来关联。
关联账号后,该组织的身份提供方可以直接以该账号登录,无需密码。它打开的会话是该账号的普通 会话,可以访问该账号所属的每一个组织,强制要求各自单点登录的组织除外。只关联你愿意交由这个身份提供方控制的账号。
仍需修改密码的会话不能关联,请求会被拒绝并返回 PASSWORD_CHANGE_REQUIRED。请先修改密码。
之后更改 NameID
连接从不替换已有的关联。当身份提供方开始为某人发送不同的 NameID 时(例如你修改了身份提供方的 NameID 来源,或 NameID 是一个已被改名的用户名),此人会被拒绝并返回 SSO_ACCOUNT_ALREADY_LINKED。要让此人重新登录,请将其移出组织(关联随之删除),再重新加入。
自动替换关联是不安全的:如果身份提供方允许用户自行修改邮箱地址,替换就可能把一个已关联的账号交给其他人。
成员如何加入
确定账号后,由组织决定是否接纳:
- 此人已是组织成员(无论是受邀加入、在控制台中创建,还是通过 SCIM 预配):直接登录。通过 SCIM 预配的成员仍由 SCIM 管理。
- 此人是等待加入的 SCIM 成员,且 NameID 等于目录发送的
externalId:关联该身份即激活该成员。参见等待加入的成员。 - 此人有待接受的组织邀请,且邀请发往账号已验证的邮箱地址,或身份提供方发送的受信任地址:邀请被接受,此人以邀请中的角色加入,除非角色映射规则给出了其他角色。
- 以上都不是,且已开启 JIT 预配:此人以默认角色或规则给出的角色加入。已有账号(例如属于其他组织的账号)会被加入本组织。
- 以上都不是,且未开启 JIT 预配:登录被拒绝并返回
SSO_NOT_A_MEMBER,也不会建立关联。请邀请此人,或通过 SCIM 预配。
成员资格已被停用(例如被 SCIM 停用)的成员无法登录,登录会被拒绝并返回 SSO_MEMBER_DEACTIVATED。
SSO 创建的账号没有密码。在 On-Premises 控制面上,管理员仍可以为其启用密码登录。
将身份提供方属性映射为角色
角色映射规则根据 SAML 断言中的属性设置成员角色。一个连接最多 50 条规则,每条规则包含 属性、运算符、值 和 角色:
| 运算符 | 控制台标签 | 命中条件 |
|---|---|---|
exact_match | 等于(第一个值) | 属性的第一个值等于该值。 |
contains_string | 包含(第一个值) | 属性的第一个值包含该值。 |
exact_match_in_array | 任一值等于 | 属性的任一值等于该值。 |
contains_string_in_array | 任一值包含 | 属性的任一值包含该值。 |
属性名按 Name 或 FriendlyName 匹配,不区分大小写;值按原样比较,区分大小写。规则按顺序检查,第一条命中的规则生效。
规则的作用:
- 有规则时,每次登录都会把成员角色设为第一条命中规则的角色;没有规则命中时设为默认角色。这同样会覆盖成员通过 SSO 登录接受的邀请中的角色,以及在控制台中手动修改的角色(在成员下次登录时)。
- 没有规则时,SSO 只在此人加入时设置角色(邀请中的角色或默认角色),之后不再修改。
- Owner 永远不会被修改,无论是否有规则。
如果组织同时使用 SCIM,SSO 写入的角色优先:SCIM 的组到角色映射不再修改该成员的角色。删除所有规则、移除连接,或在控制台中手动修改该成员的角色,都会把这些角色交还给 SCIM 管理。
被默认角色或某条规则引用的自定义角色,在连接仍使用它时无法删除。
对于 Microsoft Entra ID,指南介绍了如何定义应用角色并将其映射为 AISIX Cloud 角色。
强制单点登录
强制单点登录 使 SSO 成为 Owner 以外的成员访问组织的唯一方式。只 有已启用的连接才能开启此项。
开启后:
- Owner 以外的成员只能使用最近 24 小时内完成过本组织 SSO 的会话访问组织,即通过本组织 SSO 登录,或在关联页面确认关联。24 小时从那次登录算起,使用会话不会延长。其他组织的 SSO 不算数。否则,控制台会把他们带到 需要单点登录 页面
/sso-required?org=<org-slug>,该页面提供 SSO 登录入口;API 调用返回403,错误码为SSO_REQUIRED。该组织仍会出现在其组织列表中,便于找到。 - Owner 不受限制,始终可以用密码登录,从而在身份提供方故障或配置错误时保留进入组织的途径。
- 已有的管理令牌继续有效。
修改身份提供方实体 ID、单点登录 URL 或证书(包括添加证书)会自动关闭强制单点登录,因为新的身份提供方设置还没有经过登录验证。请先通过身份提供方成功登录一次,再重新开启。
SSO 会话
SSO 打开的会话是该账号的普通会话,与密码会话相同:
- 可以访问该账号所属的每一个组织,但须满足各组织的强制单点登录设置。
- 有效期 7 天,使用期间会自动延长。
- 与其他会话一样,可以修改账号的个人资料和密码、创建组织、接受邀请。
如果浏览器原本已以同一个人的身份登录,新会话会保留原会话完成过的 SSO 登录记录,因此通过一个组织的 SSO 登录不会让另一个 组织已有的 SSO 登录记录失效。
故障排查
SSO 登录未完成时,浏览器会回到 /login?sso=<org-slug>&sso_error=<CODE>,页面会说明错误原因。在 On-Premises 控制面上,cp-api 也会在日志中记录拒绝 SAML 响应的原因。
| 错误码 | 可能原因 | 解决方法 |
|---|---|---|
SSO_NOT_ENABLED | 没有使用该标识的组织,或其 SSO 连接未启用。登录过程中连接被停用或被替换时也会返回该错误。 | 检查组织标识,并确认已开启 启用单点登录。 |
SSO_UNSOLICITED_RESPONSE | 响应不对应任何进行中的登录:身份提供方自行发起了登录、登录已超过 10 分钟,或响应已被使用过。 | 从 AISIX Cloud 登录页面发起登录。在身份提供方中登记登录 URL(例如 Entra ID 的 Sign on URL),使其应用启动入口打开 AISIX Cloud 登录页面。 |
SSO_RESPONSE_INVALID | 响应未通过验证:可能由连接中不存在的证书签名、来自其他颁发者、指向其他受众或接收方,或不在有效期内。 | 将 身份提供商实体 ID 和证书与身份提供方核对,将在身份提供方中登记的实体 ID 和回复 URL 与 SSO 卡片核对,并检查身份提供方和控制面的时钟。 |
SSO_ENCRYPTED_ASSERTION_UNSUPPORTED | 身份提供方加密了断言。 | 在身份提供方中关闭该应用的令牌或断言加密。 |
SSO_IDP_ERROR | 身份提供方返回了失败状态。 | 在身份提供方的登录日志中 查看原因。 |
SSO_NAME_ID_MISSING | 断言中没有 NameID。 | 配置身份提供方为每个用户发送 NameID。 |
SSO_NAME_ID_TRANSIENT | NameID 为 transient 格式,只在一次登录中标识此人。 | 发送 persistent 格式的 NameID,或其他对同一个人保持不变的格式,例如不可变的用户 ID。使用 Entra ID 时,使用 user.objectid,格式为 Persistent。 |
SSO_BROWSER_MISMATCH | 登录在发起它的浏览器以外完成、耗时超过 10 分钟,或浏览器拦截了登录 Cookie。 | 在同一个浏览器中从登录页面重新发起登录。 |
SSO_NOT_A_MEMBER | 此人不是成员,没有待接受的邀请,且未开启 JIT 预配。 | 邀请此人、通过 SCIM 预配,或开启 登录时自动添加新成员(JIT)。 |
SSO_MEMBER_DEACTIVATED | 成员资格已被停用。 | 重新激活该成员,例如由 SCIM 管理时在身份提供方中重新激活。 |
SSO_ACCOUNT_ALREADY_LINKED | 该账号在此连接中已关联另一个 NameID,通常是因为身份提供方为此人发送的 NameID 变了。 | 将此人移出组织再重新加入。参见之后更改 NameID。 |
SSO_IDENTITY_ALREADY_LINKED | 在关联页面上:该身份已在此期间关联到另一个账号。 | 再次通过 SSO 登录,即会登录到那个账号。 |
SSO_CONNECT_EXPIRED | 在关联页面上:浏览器中没有等待关联的身份。它已经关联,或已超过 10 分钟。 | 再次通过 SSO 登录。 |
SSO_CLAIM_LINK_INVALID | 关联页面发出的验证链接无效、已过期、已使用,或已被更新的链接取代。 | 再次通过 SSO 登录并发送新链接。 |
INTERNAL_ERROR | 控制面处理登录时出错。 | 重试。在 On-Premises 控制面上,检查 cp-api 日志。 |
如果身份提供方自身报告回复 URL 不匹配(例如 Entra ID 的 AADSTS50011),或者所有响应都以 SSO_RESPONSE_INVALID 失败,请先检查公开 URL。SSO 卡片用它生成实体 ID 和回复 URL,因此如果该值浏览器无法访问,或在登记应用后发生了变化,所有登录都会失败。请修正 AISIX_CLOUD_PUBLIC_BASE_URL 或 api.publicBaseURL,再把 SSO 卡片中的新值复制到身份提供方。
Entra ID 在其自身页面上显示的错误(例如用户未分配到应用时的 AADSTS50105),参见 Entra ID 指南的故障排查。