多个IDP的用户联合方案的分析

网站A与网站B基于OIDC的跨站单点登录流程

技术前提

  • 网站A和网站B各自实现完整的OIDC协议(既是客户端,也是身份提供商)
  • 双方需要预先在对方的系统中注册为可信OIDC客户端
  • 双方需要相互交换OIDC配置信息(端点URL、客户端ID、JWKS等)

两个IDP的关系

时序流程

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)需要:

  1. 开放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
  2. 客户端注册

    • 为网站B创建客户端配置
    • 提供Client ID和Client Secret
    • 配置网站B的重定向URI
  3. 用户映射

    • 建立用户标识映射机制(如:sub claim映射)
    • 可选实现账号关联功能
  4. 安全配置

    • 配置CORS,允许网站B的前端请求
    • 实现PKCE支持
    • 配置适当的Token生命周期

网站B(作为客户端)需要:

  1. OIDC客户端配置

    • 配置网站A作为身份提供商
    • 设置Client ID和Client Secret
    • 配置回调地址
  2. Token验证

    • 从网站A获取JWKS公钥
    • 实现ID Token签名验证
    • 验证issuer、audience、有效期
  3. 用户会话管理

    • 创建本地会话,关联外部用户
    • 实现会话同步机制
    • 处理Token刷新逻辑
  4. 前端配置

    • 实现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"
}

安全注意事项

  1. Token验证:网站B必须验证网站A颁发的ID Token的签名
  2. 状态参数:使用state参数防止CSRF攻击
  3. PKCE:建议使用PKCE增强移动端和SPA安全性
  4. 重定向URI验证:严格验证重定向URI,防止开放重定向
  5. 用户同意:确保用户明确同意授权给第三方网站
  6. 会话管理:合理设置会话过期时间,提供注销机制

流程优化建议

  1. 静默认证:可以在用户无感知的情况下进行认证,提升用户体验
  2. 单点登出:实现跨站单点登出功能
  3. Token自动刷新:实现Access Token自动刷新机制
  4. 会话检查:定期检查用户在网站A的登录状态

通过上述流程,用户在网站A登录后,访问网站B时可以无需重新输入凭据即可登录,实现了跨站的单点登录体验。这种方式适用于两个独立系统需要共享用户认证状态,但又希望保持各自用户体系独立性的场景。

posted @ 2026-08-07 16:18  张占岭  阅读(3)  评论(0)    收藏  举报