Test points for OIDC login, user binding, HARBORFORGE_OIDC_ONLY mode, and the admin OIDC settings page, with local verification status. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6.5 KiB
6.5 KiB
OIDC 接入 — 测试点描述
覆盖范围:OIDC 登录、hf 用户与 OIDC 身份绑定、HARBORFORGE_OIDC_ONLY
模式、管理员 OIDC 配置页面。涉及仓库分支 feature/oidc-login
(HarborForge.Backend + HarborForge.Frontend)。
“本地状态” 列:✅ 已用真实 Keycloak 在本地栈端到端验证;🟡 已用接口/构建 验证但未走真实 IdP UI;⬜ 待测。
0. 测试环境
- 后端
http://127.0.0.1:18000、前端http://127.0.0.1:13000(本地验证栈) - IdP:Keycloak 容器,realm
hf,confidential clienthf-client - IdP 测试用户:
tester/Test123!(emailVerified=true) - 关键约束:issuer URL 必须浏览器与后端容器都能用同一地址访问
(否则 token
iss校验失败)。本地用宿主机 IP 统一两端。 - 配置项(运行时 env 或 DB,DB 覆盖 env):
OIDC_ENABLED / OIDC_ISSUER / OIDC_CLIENT_ID / OIDC_CLIENT_SECRET / OIDC_REDIRECT_URI / OIDC_SCOPES / OIDC_POST_LOGIN_REDIRECT; 部署级HARBORFORGE_OIDC_ONLY(Docker ARG/ENV,前后端均有)。
1. 管理员 OIDC 配置(页面 + API)
| # | 测试点 | 步骤 | 预期 | 本地 |
|---|---|---|---|---|
| 1.1 | 读取初始配置 | GET /auth/oidc/settings(admin) |
返回 source=env,has_client_secret=false,effective_enabled 反映 env |
✅ |
| 1.2 | 保存配置 | PUT /auth/oidc/settings 填 issuer/client/secret/redirect/scopes/post_login |
200,source=db,effective_enabled=true |
✅ |
| 1.3 | client_secret 只写不回显 | 保存后再 GET |
响应无明文 secret,仅 has_client_secret=true |
✅ |
| 1.4 | secret 留空保留原值 | PUT 不带 client_secret |
原 secret 不变,登录仍可用 | 🟡 |
| 1.5 | 配置即时生效 | 保存后 GET /auth/config |
oidc_enabled 立即变化,无需重启 |
✅ |
| 1.6 | 页面仅 admin 可见 | 非 admin 访问 /settings/oidc |
被重定向到 /;侧栏无入口;API 返回 401/403 |
🟡 |
| 1.7 | 页面展示 Callback URL | 打开 OIDC 设置页 | 醒目显示需在 IdP 注册的 redirect/callback URL、当前状态与配置来源 | 🟡 |
2. OIDC 登录流程(授权码)
| # | 测试点 | 步骤 | 预期 | 本地 |
|---|---|---|---|---|
| 2.1 | 发起登录 | GET /auth/oidc/login |
302 跳转到 IdP authorize 端点(state/nonce 入会话 cookie) | ✅ |
| 2.2 | IdP 登录成功回跳 | 在 IdP 输入 tester/Test123! |
302 回 …/auth/oidc/callback?code=…&state=… |
✅ |
| 2.3 | 回调换码并签发 | 后端处理 callback | 校验 ID token(JWKS)→定位绑定用户→签发 hf JWT→302 到前端 post_login#token=… |
✅ |
| 2.4 | 登录态可用 | 用返回 token 调 GET /auth/me |
返回被绑定的 hf 用户 | ✅ |
| 2.5 | 前端按钮 | 登录页点 “Sign in with SSO” | 全页跳转到后端 /auth/oidc/login |
🟡 |
| 2.6 | 未配置 OIDC | OIDC 关闭时访问 /auth/oidc/login |
503 “OIDC is not configured” | 🟡 |
| 2.7 | token 交换失败 | code 失效/被篡改 | 回前端 ?oidc_error=exchange_failed,登录页提示 |
⬜ |
3. hf 用户 ↔ OIDC 身份绑定
| # | 测试点 | 步骤 | 预期 | 本地 |
|---|---|---|---|---|
| 3.1 | 管理员绑定 | PUT /users/{id}/oidc-binding {issuer,subject}(admin 或 acc-manager) |
200,用户响应含 oidc_issuer/oidc_subject |
✅ |
| 3.2 | 未绑定身份拒绝登录 | 解绑后用该 IdP 账号登录 | 回 ?oidc_error=not_linked,不签发 token(不自动开号) |
✅ |
| 3.3 | 身份唯一性 | 把同一 (issuer,subject) 绑到另一用户 | 409 冲突 | ✅ |
| 3.4 | 解绑 | DELETE /users/{id}/oidc-binding |
200,绑定清空 | ✅ |
| 3.5 | 绑定鉴权 | 无凭据 / 普通用户调用绑定 API | 401 / 403 | ✅ |
| 3.6 | API key 通道 | admin 的 API key 调用绑定/配置 API | 200(支持 JWT 或 API key) | ✅ |
| 3.7 | 自助绑定(非 ONLY) | 登录用户点侧栏 “Link OIDC account” 走一次 OIDC | 回 ?oidc_linked=1,当前账号绑定成功 |
🟡 |
| 3.8 | 自助绑定冲突 | 自助绑定到已被占用的身份 | ?oidc_error=already_bound |
⬜ |
| 3.9 | OIDC_ONLY 下禁自助 | ONLY 模式访问 /auth/oidc/link |
403(仅管理员 API 可绑) | 🟡 |
4. HARBORFORGE_OIDC_ONLY 模式
| # | 测试点 | 步骤 | 预期 | 本地 |
|---|---|---|---|---|
| 4.1 | 配置反映 | ONLY=true 时 GET /auth/config |
oidc_only=true,password_login=false |
✅ |
| 4.2 | 禁用密码登录 | POST /auth/token |
403 “Password login is disabled (OIDC only)” | ✅ |
| 4.3 | 建用户忽略密码 | POST /users 带 password |
201,但 DB hashed_password=NULL(无密码用户) |
✅ |
| 4.4 | 改用户忽略密码 | PATCH /users/{id} 带 password |
密码不被设置 | 🟡 |
| 4.5 | 无密码用户仍可用 | 对该用户绑定 OIDC、生成 API key | 绑定 200、reset-apikey 200;可经 OIDC 登录 |
✅ |
| 4.6 | 前端隐藏密码 UI | ONLY 模式打开登录页 / 用户管理页 | 无用户名密码框;用户管理无密码/重置密码组件 | 🟡 |
| 4.7 | 防锁死恢复 | ONLY 模式且 OIDC 配错 | 管理员 API key 仍可调 GET/PUT /auth/oidc/settings 修复 |
✅ |
5. 回归(不破坏既有功能)
| # | 测试点 | 步骤 | 预期 | 本地 |
|---|---|---|---|---|
| 5.1 | 默认模式密码登录 | 未开 ONLY 时 POST /auth/token |
正常 200 签发 token | ✅ |
| 5.2 | 用户响应新增字段 | GET /users /users/{id} /auth/me |
含 oidc_issuer/oidc_subject(未绑定为 null) |
✅ |
| 5.3 | 启动迁移幂等 | 新旧库重复启动后端 | users.oidc_* 列与 oidc_settings 表存在,无报错 |
✅ |
| 5.4 | 前端构建 | npm run build(Docker 镜像) |
TS 编译通过 | ✅ |
| 5.5 | 后端导入 | 镜像内 import app.main |
无导入错误,OIDC 路由注册 | ✅ |
| 5.6 | 镜像参数 | 前后端 Dockerfile | 含 ARG/ENV HARBORFORGE_OIDC_ONLY |
✅ |
6. 安全检查点
- ID token 经 IdP JWKS 校验(Authlib discovery + nonce);签发的是 hf 原有
HS256 JWT,依赖强
SECRET_KEY(弱 key 后端拒绝启动)。 client_secret持久化在 DB,接口永不回显。- 绑定/配置接口强制 admin(或 account-manager 绑定),支持 API key 作为 OIDC_ONLY 下的恢复通道。
- 未绑定 OIDC 身份一律拒绝,不自动开号(防越权开户)。
redirect_uri必须在 IdP 精确注册;后端回跳前端地址来自服务端配置 (post_login_redirect),不接受客户端传入,避免开放重定向。
7. 已知限制 / 待补
- 真实浏览器交互(点按钮、IdP 同意页、SameSite cookie 行为)需人工过一遍 (本地已用 curl 无头跑通授权码全流程,逻辑等价)。
- 多 IdP / 多 issuer、token 刷新、登出联动(SLO)未实现,超出本次范围。
- 自助绑定相关 UI(3.7/3.8)建议人工在浏览器复核。