Skip to content

✨ 实现客户端凭据生命周期与紧急撤销 - #3

Merged
UE-DND merged 3 commits into
masterfrom
codex/client-secret-lifecycle
Jul 13, 2026
Merged

✨ 实现客户端凭据生命周期与紧急撤销#3
UE-DND merged 3 commits into
masterfrom
codex/client-secret-lifecycle

Conversation

@UE-DND

@UE-DND UE-DND commented Jul 13, 2026

Copy link
Copy Markdown
Member

概要

第三轮改造客户端凭据生命周期与紧急撤销。保留现有 Revision 审批、管理会话、CSRF、OIDC 登录和 scrypt 格式,不引入旧库迁移或范围外能力。

数据模型

  • oidc_clients 移除 Secret 摘要,新建 oidc_client_secrets,记录 secret_id、客户端、scrypt 摘要、active/retiring/revoked、创建/到期/撤销时间和版本。
  • 每个客户端至多一个 active Secret,事务内至多两个未过期可用 Secret。
  • oidc_artifacts 增加基于现有 Artifact HMAC 密钥的不可逆 client_id_hash 索引。
  • 为客户端和 Artifact 增加单调递增的 authorization_generation,将签发请求绑定到撤销前读取的授权代际。
  • 审计记录增加可选 secret_id 和轮换、指定撤销、授权撤销、紧急停用操作,不记录 Secret 明文或摘要。

Secret 状态机

  • 创建 Web Client 时生成 active Secret。
  • 正宽限期轮换:旧 active 转 retiring 并设置到期时间,新 Secret 成为 active。
  • 零宽限期轮换:旧 Secret 立即 revoked,新 Secret 成为 active。
  • active/retiring 可立即撤销为 revoked;revoked 为终态。
  • retiring 到期后由认证查询动态排除,无需后台任务。

API 与 OIDC

  • POST /clients/:clientId/secrets/rotate
  • POST /clients/:clientId/secrets/:secretId/revoke
  • POST /clients/:clientId/authorizations/revoke
  • POST /clients/:clientId/disable 升级为原子紧急停用、撤销全部 Secret/授权并取消开放 Revision。
  • OIDC 动态验证该客户端全部未过期可用 scrypt 摘要,任一匹配即通过。
  • PostgreSQL OIDC 热路径只查询 active 或数据库 now() 下尚未到期的 retiring Secret,不加载历史摘要。
  • 新增默认/最大宽限期环境变量;部署期 bootstrap digest 仍受支持,管理 API 严格拒绝明文、摘要、目标状态和额外字段。

安全设计

  • 所有管理操作复用登录会话、owner/admin 授权、CSRF、来源 IP 与客户端/Secret 双重乐观锁。
  • Secret 明文仅在创建或轮换响应展示一次;公开模型、查询 API 和审计均不暴露明文或摘要,无恢复历史 Secret 路径。
  • 客户端级撤销仅删除 Authorization Code、Access Token、Refresh Token 和 Grant;保留用户 OP Session,并隔离其他客户端。
  • 授权撤销和紧急停用在删除 Artifact 的事务内递增 Generation;Artifact 每次读取检查客户端状态与 Generation,撤销提交后的迟到 Token 写入也不可使用。
  • PostgreSQL 操作锁定客户端行,在单事务中更新版本、Secret、Artifact、Revision 和审计。
  • Secret 轮换在 scrypt 前执行版本、可用数量和冷却预检,并按主体、客户端、来源 IP 三维限流;事务内仍执行最终校验。
  • PostgreSQL 使用数据库 now() 生成轮换创建时间、宽限期、到期判断和冷却判断,避免多实例应用时钟偏差。

界面与文档

  • 管理界面展示 Secret 标识、状态、创建/到期/撤销时间以及宽限期已到期状态。
  • 增加轮换、指定撤销、全部授权撤销和不可恢复的紧急停用确认流程,以及一次性 Secret 面板。
  • 宽限期输入从服务端策略读取,不再硬编码 168 小时;Secret 历史分页展示,终态历史按最近 100 条保留,完整轨迹留在无摘要审计中。
  • 更新 README、环境变量和 Compose 配置说明。

验证结果

  • pnpm format:通过
  • pnpm lint:通过
  • TEST_DATABASE_URL=postgres://postgres:test@127.0.0.1:55432/cqut_auth_test pnpm test:服务端 154/154,通过且 0 跳过;管理 UI 8/8 通过
  • pnpm build:通过
  • pnpm docker:build:通过
  • pnpm docker:up + /health/ready:PostgreSQL、Redis、OIDC 服务均 healthy,readiness 返回 database=postgres、redis=ready;随后 pnpm docker:down 正常关闭

审查修复验证

  • 使用同步屏障模拟撤销提交后才写入的 Access Token,确认旧 Generation Artifact 无法读取。
  • 真实 OidcPersistenceImpl + PostgreSQL 完成 Authorization Code + PKCE、Access/Refresh 签发、HMAC Client Hash 数据库断言、客户端撤销、UserInfo/Refresh 失效和 OP Session 复用。
  • PostgreSQL 时钟偏移测试确认轮换响应的 created_atexpires_at 来自数据库时间。
  • 零宽限期连续轮换测试确认三维限流和最短冷却在 scrypt 计算前生效。

@UE-DND
UE-DND marked this pull request as ready for review July 13, 2026 14:03
@UE-DND
UE-DND merged commit bccd10a into master Jul 13, 2026
9 of 10 checks passed
@UE-DND
UE-DND deleted the codex/client-secret-lifecycle branch July 13, 2026 14:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant