easyai-ai-gateway/docs/oidc-jit-provisioning.md
chengcheng a81a7b5200 fix: 修复 OIDC 用户预配与跨标签页登录态
增加受控 JIT 本地用户投影,并使用 HttpOnly Cookie 在新标签页恢复认证中心登录态。补充错误语义、安全校验、自动化测试与回滚配置。
2026-07-13 17:07:52 +08:00

4.9 KiB
Raw Blame History

Auth Center OIDC 用户受控 JIT 预配

适用边界

Gateway 只在 OIDC Token 已通过签名、Issuer、Audience、有效期、tid、Scope 和应用角色校验后执行 JIT。认证中心的稳定 sub 是外部用户标识Gateway 不读取、不保存或公开 Keycloak 内部 ID也不向 Token 增加 gatewayUserId

本次保持单 Gateway 租户:部署方用 OIDC_GATEWAY_TENANT_KEY 把 Auth Center 的已验证 tid 显式绑定到一个已存在、启用且配置了启用中默认用户组的 Gateway 租户。Token 不能创建租户。

配置

OIDC_ENABLED=true
OIDC_JIT_PROVISIONING_ENABLED=true
OIDC_GATEWAY_TENANT_KEY=default
OIDC_BROWSER_SESSION_ENABLED=true
OIDC_SESSION_COOKIE_SECURE=false # 本地 HTTP生产必须为 true
  • OIDC_JIT_PROVISIONING_ENABLED 默认 false。关闭时停止创建新用户,但已有 source=oidc + external_user_id=sub 映射仍会解析和同步登录时间。
  • JIT 开启时 OIDC_GATEWAY_TENANT_KEY 必填,缺失会使 Gateway 启动失败。
  • 本地与 Staging 验收环境应在各自 Git 忽略或 Secret 管理的环境文件中显式开启;生产启用需独立变更审批。

Web Console 浏览器会话

  • OIDC 回调仍使用 Authorization Code + PKCE 从 Auth Center 获取 Access Token但 Token 只在回调函数内存中短暂存在。
  • Web 随即调用 POST /api/v1/auth/oidc/sessionGateway 再次完成全部 OIDC 校验后,将原 Auth Center Access Token 写入 HttpOnly + SameSite=Strict Cookie不签发第二枚 Gateway JWT。
  • Cookie 有效期不超过 Access Token 的 exp,所有 Cookie 请求仍经过 JWKS、Issuer、Audience、tid、Scope、角色及可选 Introspection 校验。
  • 建立成功后清除旧的 OIDC sessionStorage 和可能冲突的 localStorage Token新标签页通过 Cookie 调用 /api/v1/me 自动恢复同一登录态。
  • 所有 Web API 请求使用 credentials: include。Cookie 鉴权的 POST、PUT、PATCH、DELETE 必须携带 CORS_ALLOWED_ORIGIN 白名单中的 Origin否则返回结构化 403。
  • Staging、生产及其他非本地环境启动时强制 OIDC_SESSION_COOKIE_SECURE=true,并拒绝带 * 的凭据型 CORS 配置。本地 HTTP 开发和自动化测试可以显式设为 false
  • DELETE /api/v1/auth/oidc/session 使 Cookie 立即过期,然后前端进入 Auth Center OIDC 登出。浏览器会话关闭时不会创建或撤销 Gateway API Key。
  • 回滚时同时设置后端 OIDC_BROWSER_SESSION_ENABLED=false 和 Web 构建参数 VITE_OIDC_BROWSER_SESSION_ENABLED=false,恢复旧的标签页级 sessionStorage 行为。

数据和事务语义

  • 查找键固定为 source=oidc + external_user_id=subuser_key 由规范化 Issuer 和 sub 做 SHA-256 派生,不按邮箱、手机号、昵称匹配。
  • 首次登录在一个事务中创建 gateway_users 投影、绑定租户默认用户组、初始化 resource 钱包并写入 identity.oidc_user.provisioned 审计事件。
  • 重复或并发登录依赖现有唯一约束和冲突处理返回同一个本地用户,不重复创建钱包或首次预配审计。
  • 后续登录只同步 Token 用户名、应用角色、last_login_atsynced_atsource_updated_at;不覆盖人工资料或用户组,不重新启用已禁用/删除账号。
  • JIT 不生成 API Key 或任何 secret。用户仅在主动创建 API Key 或进入需要 Key 的工作流时触发生命周期操作。

对外错误

所有错误沿用 ErrorEnvelope

HTTP code 含义
403 GATEWAY_USER_NOT_PROVISIONED JIT 关闭且没有已有本地映射
403 GATEWAY_USER_DISABLED 本地用户已禁用或删除
503 GATEWAY_TENANT_UNAVAILABLE 配置租户或用户组不存在/未启用
503 GATEWAY_USER_PROVISIONING_FAILED 事务或存储故障;响应不暴露内部错误
404 OIDC_BROWSER_SESSION_DISABLED Gateway 浏览器会话功能未启用
401 OIDC_SESSION_INVALID 不是有效的 Auth Center OIDC Access Token 或已过期
400 OIDC_SESSION_TOKEN_TOO_LARGE Access Token 超过安全 Cookie 大小限制
403 OIDC_SESSION_CSRF_REJECTED Cookie 写请求缺少可信 Origin

ErrLocalUserRequired 仅作为防御性内部错误保留,对外统一转换为结构化 403。

验收与回滚

自动化门禁通过后,依次验证本地真实 OIDC 和 auth.51easyai.com Staging 专用测试租户。证据应包含脱敏 Claims、网络截图、本地 Gateway 用户记录、Trace ID、Gateway/Auth Center 审计 ID及 200/401/403/503 负向证据;不得保存 Token、授权码、密码或 Secret。

JIT 回滚时关闭 OIDC_JIT_PROVISIONING_ENABLED 并回退 Gateway 镜像。浏览器 Cookie 会话可通过后端和 Web 两侧的独立开关关闭。已经创建的 source=oidc 测试投影保留为惰性数据,不自动删除、迁移或合并。