多个IDP的用户联合方案的分析
网站A与网站B基于OIDC的跨站单点登录流程
技术前提
- 网站A和网站B各自实现完整的OIDC协议(既是客户端,也是身份提供商)
- 双方需要预先在对方的系统中注册为可信OIDC客户端
- 双方需要相互交换OIDC配置信息(端点URL、客户端ID、JWKS等)
两个IDP的关系
- 从site-a环境完成认证时,直接与site-b完成了用户映射
- 从site-a认证时,会先idp为site-b的认证服务,完成认证后,回到test-a中绑定本地用户,这时在site-a中可以看到用户绑定有关系,而在site-b中是没有这种关系的,site-b-auto客户端指定了一个site-b的idp认证器
- 认证URL:https://site-a.kc.com/auth/realms/kc/protocol/openid-connect/auth?scope=openid&response_type=code&client_id=site-b-auto&redirect_uri=https://test1.kc.com
- 操作流程,可以先在site-b中先登录,然后在它里点site-a上面的连接,来完成site-a与site-b的用户绑定,绑定关系在site-a里
时序流程
sequenceDiagram
participant 用户
participant 网站A
participant 网站B
Note over 用户,网站A: 阶段1: 用户在网站A登录
用户->>网站A: 1. 访问网站A
网站A->>网站A: 2. 检查本地会话(未登录)
网站A->>用户: 3. 重定向到网站A的OIDC授权端点
用户->>网站A: 4. 在网站A登录页面输入凭据
网站A->>网站A: 5. 验证用户凭据
网站A->>网站A: 6. 创建本地会话,生成ID Token
网站A->>用户: 7. 重定向回网站A并设置会话Cookie
用户->>网站A: 8. 访问网站A受保护资源
网站A->>用户: 9. 返回受保护内容
Note over 用户,网站B: 阶段2: 访问网站B,触发SSO
用户->>网站B: 10. 访问网站B
网站B->>网站B: 11. 检查本地会话(未登录)
网站B->>用户: 12. 重定向到网站B的OIDC授权端点
用户->>网站B: 13. 到达网站B授权端点(携带state参数)
Note over 网站B,网站A: 网站B作为客户端,网站A作为IdP
网站B->>用户: 14. 重定向到网站A(作为第三方IdP)
用户->>网站A: 15. 到达网站A的第三方授权端点
网站A->>网站A: 16. 检查用户是否已登录(是,跳过登录界面)
网站A->>用户: 17. 显示授权同意页面
用户->>网站A: 18. 用户同意授权
网站A->>用户: 19. 重定向回网站B回调地址(携带授权码)
用户->>网站B: 20. 到达网站B回调地址
网站B->>网站A: 21. 用授权码请求Token(后端通信)
网站A->>网站B: 22. 返回ID Token、Access Token
网站B->>网站B: 23. 验证ID Token签名
网站B->>网站A: 24. (可选)调用UserInfo端点
网站A->>网站B: 25. 返回用户信息
网站B->>网站B: 26. 创建本地会话,关联网站A用户
网站B->>用户: 27. 设置网站B会话Cookie
用户->>网站B: 28. 访问网站B受保护资源
网站B->>用户: 29. 返回受保护内容
双方需要做的具体工作
网站A(作为IdP)需要:
-
开放OIDC端点
- 授权端点:
https://site-a.com/oauth/authorize - Token端点:
https://site-a.com/oauth/token - UserInfo端点:
https://site-a.com/oauth/userinfo - JWKS端点:
https://site-a.com/.well-known/jwks.json - 发现端点:
https://site-a.com/.well-known/openid-configuration
- 授权端点:
-
客户端注册
- 为网站B创建客户端配置
- 提供Client ID和Client Secret
- 配置网站B的重定向URI
-
用户映射
- 建立用户标识映射机制(如:
subclaim映射) - 可选实现账号关联功能
- 建立用户标识映射机制(如:
-
安全配置
- 配置CORS,允许网站B的前端请求
- 实现PKCE支持
- 配置适当的Token生命周期
网站B(作为客户端)需要:
-
OIDC客户端配置
- 配置网站A作为身份提供商
- 设置Client ID和Client Secret
- 配置回调地址
-
Token验证
- 从网站A获取JWKS公钥
- 实现ID Token签名验证
- 验证issuer、audience、有效期
-
用户会话管理
- 创建本地会话,关联外部用户
- 实现会话同步机制
- 处理Token刷新逻辑
-
前端配置
- 实现OIDC客户端JS库
- 处理授权码流程
- 管理前端Token存储
关键配置示例
网站A的OIDC提供方配置:
{
"issuer": "https://site-a.com",
"authorization_endpoint": "https://site-a.com/oauth/authorize",
"token_endpoint": "https://site-a.com/oauth/token",
"userinfo_endpoint": "https://site-a.com/oauth/userinfo",
"jwks_uri": "https://site-a.com/.well-known/jwks.json",
"scopes_supported": ["openid", "profile", "email"],
"response_types_supported": ["code"],
"subject_types_supported": ["public"]
}
网站B的OIDC客户端配置:
{
client_id: "site-b-client-id",
client_secret: "site-b-client-secret",
redirect_uri: "https://site-b.com/auth/callback",
authorization_endpoint: "https://site-a.com/oauth/authorize",
token_endpoint: "https://site-a.com/oauth/token",
userinfo_endpoint: "https://site-a.com/oauth/userinfo",
jwks_uri: "https://site-a.com/.well-known/jwks.json",
scope: "openid profile email"
}
安全注意事项
- Token验证:网站B必须验证网站A颁发的ID Token的签名
- 状态参数:使用state参数防止CSRF攻击
- PKCE:建议使用PKCE增强移动端和SPA安全性
- 重定向URI验证:严格验证重定向URI,防止开放重定向
- 用户同意:确保用户明确同意授权给第三方网站
- 会话管理:合理设置会话过期时间,提供注销机制
流程优化建议
- 静默认证:可以在用户无感知的情况下进行认证,提升用户体验
- 单点登出:实现跨站单点登出功能
- Token自动刷新:实现Access Token自动刷新机制
- 会话检查:定期检查用户在网站A的登录状态
通过上述流程,用户在网站A登录后,访问网站B时可以无需重新输入凭据即可登录,实现了跨站的单点登录体验。这种方式适用于两个独立系统需要共享用户认证状态,但又希望保持各自用户体系独立性的场景。
浙公网安备 33010602011771号