easyai-ai-gateway/docs/oidc-jit-provisioning.md
chengcheng 5b8178b703 docs(identity): 记录统一认证恢复与重配边界
补充管理员从 Active 禁用到新接入码重配的标准流程,说明 credentials_saved 恢复、SSF 凭据交接、持久清理、Break-glass 与动态 Origin 边界,并明确历史 Revision 仅作审计、当前不支持直接回滚。
2026-07-17 18:32:04 +08:00

6.2 KiB
Raw Permalink Blame History

Auth Center OIDC 用户受控 JIT 预配

适用边界

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

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

配置

OIDC、JIT 和浏览器会话不读取业务环境变量。管理员在 Auth Center 的通用“应用接入”向导选择 OIDC 登录API 验证,生成一次性接入码;再到 Gateway“系统设置 → 统一认证”提交认证中心地址、接入码、Gateway API/Web 地址和本地租户映射。系统自动推导回调及退出地址,生成 Session 加密密钥并保存到部署级 SecretStore。

  • JIT、Legacy JWT 兼容和 Session 时限属于 Revision 策略,可在 Draft 中修改;默认闲置 30 分钟、绝对 8 小时、提前 60 秒刷新。
  • JIT 关闭时停止创建新用户,但已有 source=oidc + external_user_id=sub 映射仍会解析和同步登录时间。
  • 本地租户不存在、公共 Client 不可用或 Discovery/Issuer/JWKS 校验失败时Revision 不能激活,当前 Active Runtime 不受影响。

Web Console 浏览器会话

  • Web 只跳转 GET /api/v1/auth/oidc/login。Gateway 生成 state、nonce、PKCE verifier并以 Authorization Code + PKCE S256 完成换码;公共 Client 请求只发送 client_id,不使用 Client Secret。
  • Access Token、Refresh Token 和 ID Token 使用 AES-256-GCM 加密后存入 PostgreSQL数据库只保存随机 Session Cookie 的 SHA-256。浏览器 JavaScript、响应体和 Web Storage 均不接触 Token。
  • 浏览器只保存 32 字节随机、HttpOnly + SameSite=Strict 的 Session Cookie。新标签页通过该 Cookie 调用 /api/v1/me 恢复登录态Gateway 不签发第二枚 JWT。
  • Access Token 继续保持 5 分钟。认证请求发现剩余时间不超过 60 秒时使用 Refresh Token 自动刷新;多实例通过 PostgreSQL 刷新租约保证同一版本只刷新一次,并原子保存旋转后的 Refresh Token。
  • Session 闲置 30 分钟、绝对最长 8 小时。闲置 530 分钟后的首个请求可自动刷新;超过闲置或绝对期限不会刷新,必须重新登录。浏览器不运行定时刷新。
  • 所有 Web API 请求使用 credentials: include。Cookie 鉴权请求的 Origin 必须与当前健康 Active Revision 的 Gateway Web 地址精确匹配,否则返回结构化 403不接受 *
  • Cookie 的 Secure 属性由 Revision 中的 Gateway API 公网地址推导:生产地址只允许 HTTPS本地开发允许 localhost HTTP。可信 Origin 由 Gateway Web 地址精确推导,不接受 *
  • POST /api/v1/auth/oidc/logout 校验可信 Origin、删除本地 Session、使用公共 Client ID 撤销 Refresh Token并跳转 Auth Center 退出地址;DELETE /api/v1/auth/oidc/session 保留为幂等的本地删除接口。
  • 第一次接入、确认禁用或 Active Runtime 故障恢复时,跨 Origin 管理页面使用部署级精确 bootstrap CORS生产部署建议由反向代理通过同源 /gateway-api 暴露 API。该配置不包含 Issuer、Client 或 Scope。
  • Session Encryption Key 由 Gateway 服务端生成,只以 Secret 引用进入 Revision不得复用 JWT Secret也不会进入数据库、响应、日志或浏览器。禁用统一认证会清理现有 BFF Session重新配对后用户需要重新登录。

数据和事务语义

  • 查找键固定为 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 Session 不存在、Cookie 格式错误或 Token 身份不匹配
401 OIDC_SESSION_EXPIRED 闲置/绝对期限已到或 Refresh Token 已失效
503 OIDC_SESSION_REFRESH_UNAVAILABLE Access Token 已过期且认证中心暂时不可用
503 OIDC_SESSION_STORE_UNAVAILABLE 数据库或 Token 密文不可用
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。

Active Revision 可原位重新验证。需要改变远端身份资源时,先确认本地 Break-glass Manager禁用当前配置再使用 Auth Center 新接入码创建、验证和激活新 Revision历史 superseded Revision 只用于审计,不能直接回滚或重新激活。已经创建的 source=oidc 测试投影保留为惰性数据,不自动删除、迁移或合并。