Files
HarborForge.Backend/docs/oidc-test-plan.md
hzhang ffce4298c8 docs: OIDC feature test plan / test points
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>
2026-05-17 20:40:26 +01:00

6.5 KiB
Raw Blame History

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(本地验证栈)
  • IdPKeycloak 容器realm hfconfidential client hf-client
  • IdP 测试用户:tester / Test123!emailVerified=true
  • 关键约束:issuer URL 必须浏览器与后端容器都能用同一地址访问 (否则 token iss 校验失败)。本地用宿主机 IP 统一两端。
  • 配置项(运行时 env 或 DBDB 覆盖 env OIDC_ENABLED / OIDC_ISSUER / OIDC_CLIENT_ID / OIDC_CLIENT_SECRET / OIDC_REDIRECT_URI / OIDC_SCOPES / OIDC_POST_LOGIN_REDIRECT 部署级 HARBORFORGE_OIDC_ONLYDocker ARG/ENV前后端均有

1. 管理员 OIDC 配置(页面 + API

# 测试点 步骤 预期 本地
1.1 读取初始配置 GET /auth/oidc/settingsadmin 返回 source=envhas_client_secret=falseeffective_enabled 反映 env
1.2 保存配置 PUT /auth/oidc/settings 填 issuer/client/secret/redirect/scopes/post_login 200source=dbeffective_enabled=true
1.3 client_secret 只写不回显 保存后再 GET 响应无明文 secrethas_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=truepassword_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 buildDocker 镜像) 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未实现超出本次范围。
  • 自助绑定相关 UI3.7/3.8)建议人工在浏览器复核。