refactor(identity): 统一网页认证配置来源
移除旧 OIDC_* 与 VITE_OIDC_* 业务配置读取,统一使用数据库 Revision 和 SecretStore 引用构建运行时。同步更新 Compose、示例配置、接入文档及集成测试,并保留数据库、SecretStore 和安全事件健康窗口等部署级参数。\n\n验证:go test ./...;go test -race ./...;go vet ./...;pnpm test;pnpm lint;pnpm build;docker compose config -q
This commit is contained in:
@@ -4,28 +4,15 @@
|
||||
|
||||
Gateway 只在 OIDC Token 已通过签名、Issuer、Audience、有效期、`tid`、Scope 和应用角色校验后执行 JIT。认证中心的稳定 `sub` 是外部用户标识;Gateway 不读取、不保存或公开 Keycloak 内部 ID,也不向 Token 增加 `gatewayUserId`。
|
||||
|
||||
本次保持单 Gateway 租户:部署方用 `OIDC_GATEWAY_TENANT_KEY` 把 Auth Center 的已验证 `tid` 显式绑定到一个已存在、启用且配置了启用中默认用户组的 Gateway 租户。Token 不能创建租户。
|
||||
本次保持单 Gateway 租户:管理员在统一认证 Draft 中把 Auth Center 的已验证 `tid` 显式绑定到一个已存在、启用且配置了启用中默认用户组的 Gateway 租户。Token 不能创建租户。
|
||||
|
||||
## 配置
|
||||
|
||||
```dotenv
|
||||
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_CLIENT_ID=<Control Plane 生成的公共 Client ID>
|
||||
OIDC_REDIRECT_URI=http://localhost:8088/api/v1/auth/oidc/callback
|
||||
OIDC_POST_LOGOUT_REDIRECT_URI=http://localhost:5178/
|
||||
OIDC_SESSION_ENCRYPTION_KEY=<独立的 32 字节随机密钥,base64 编码>
|
||||
OIDC_SESSION_IDLE_TTL_SECONDS=1800
|
||||
OIDC_SESSION_ABSOLUTE_TTL_SECONDS=28800
|
||||
OIDC_SESSION_REFRESH_BEFORE_SECONDS=60
|
||||
```
|
||||
OIDC、JIT 和浏览器会话不读取业务环境变量。管理员在 Auth Center 的通用“应用接入”向导选择 `OIDC 登录` 与 `API 验证`,生成一次性接入码;再到 Gateway“系统设置 → 统一认证”提交认证中心地址、接入码、Gateway API/Web 地址和本地租户映射。系统自动推导回调及退出地址,生成 Session 加密密钥并保存到部署级 SecretStore。
|
||||
|
||||
- `OIDC_JIT_PROVISIONING_ENABLED` 默认 `false`。关闭时停止创建新用户,但已有 `source=oidc + external_user_id=sub` 映射仍会解析和同步登录时间。
|
||||
- JIT 开启时 `OIDC_GATEWAY_TENANT_KEY` 必填,缺失会使 Gateway 启动失败。
|
||||
- 本地与 Staging 验收环境应在各自 Git 忽略或 Secret 管理的环境文件中显式开启;生产启用需独立变更审批。
|
||||
- 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 浏览器会话
|
||||
|
||||
@@ -35,9 +22,9 @@ OIDC_SESSION_REFRESH_BEFORE_SECONDS=60
|
||||
- Access Token 继续保持 5 分钟。认证请求发现剩余时间不超过 60 秒时使用 Refresh Token 自动刷新;多实例通过 PostgreSQL 刷新租约保证同一版本只刷新一次,并原子保存旋转后的 Refresh Token。
|
||||
- Session 闲置 30 分钟、绝对最长 8 小时。闲置 5~30 分钟后的首个请求可自动刷新;超过闲置或绝对期限不会刷新,必须重新登录。浏览器不运行定时刷新。
|
||||
- 所有 Web API 请求使用 `credentials: include`。Cookie 鉴权的 POST、PUT、PATCH、DELETE 必须携带 `CORS_ALLOWED_ORIGIN` 白名单中的 Origin,否则返回结构化 403。
|
||||
- Staging、生产及其他非本地环境启动时强制 `OIDC_SESSION_COOKIE_SECURE=true`,并拒绝带 `*` 的凭据型 CORS 配置。本地 HTTP 开发和自动化测试可以显式设为 `false`。
|
||||
- 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` 保留为幂等的本地删除接口。
|
||||
- `OIDC_SESSION_ENCRYPTION_KEY` 必须来自 Git 忽略的本地文件、Kubernetes Secret 或 Secret Manager,不得复用 JWT Secret。关闭 `OIDC_BROWSER_SESSION_ENABLED` 可停止新会话;回滚镜像后已创建记录作为惰性数据保留。
|
||||
- Session Encryption Key 由 Gateway 服务端生成,只以 Secret 引用进入 Revision,不得复用 JWT Secret,也不会进入数据库、响应、日志或浏览器。禁用统一认证会清理现有 BFF Session;回滚后用户需要重新登录。
|
||||
|
||||
## 数据和事务语义
|
||||
|
||||
@@ -70,4 +57,4 @@ OIDC_SESSION_REFRESH_BEFORE_SECONDS=60
|
||||
|
||||
自动化门禁通过后,依次验证本地真实 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` 测试投影保留为惰性数据,不自动删除、迁移或合并。
|
||||
JIT 策略变更通过创建并验证新 Revision 后激活;身份配置回滚使用“系统设置 → 统一认证”的回滚操作。激活、回滚和禁用均要求本地 Break-glass Manager 可用,并清理受影响的 BFF Session。已经创建的 `source=oidc` 测试投影保留为惰性数据,不自动删除、迁移或合并。
|
||||
|
||||
@@ -1,36 +1,35 @@
|
||||
# SSF/CAEP 实时会话撤销运行手册
|
||||
|
||||
Gateway 可选接收 Auth Center 通过 RFC 8935 Push 投递的 RFC 8417 Security Event Token,并处理 OpenID CAEP `session-revoked`。功能由数据库中的连接资源控制:没有连接时保持原有 OIDC、BFF、API Key 和 Legacy JWT 行为;不再使用 `OIDC_SECURITY_EVENTS_ENABLED`。
|
||||
Gateway 可选接收 Auth Center 通过 RFC 8935 Push 投递的 RFC 8417 Security Event Token,并处理 OpenID CAEP `session-revoked`。能力由 Active Identity Revision 控制;没有选择会话撤销时保持原有 OIDC、BFF、API Key 和 Legacy JWT 行为。
|
||||
|
||||
## 用户接入流程
|
||||
|
||||
用户只执行两项操作:
|
||||
首次接入只执行两端各一次操作:
|
||||
|
||||
1. 在认证中心 Application 的“安全事件流”页面选择现有 RFC 7662 机器 Client,点击“准备 Gateway 接入”。认证中心自动合并 SSF 管理 Scope;不会创建第二个 Client。
|
||||
2. Receiver 就绪后点击“生成一次性连接凭据”,立即复制 machine Client ID/Secret。
|
||||
3. 在 Gateway“系统设置 → 认证中心安全事件”中填写 SSF Issuer 和这组一次性凭据,点击“连接认证中心”。
|
||||
1. 在认证中心 Application 的通用“应用接入”向导选择“SSF 会话撤销”。能力依赖会自动包含 Token Introspection 和机器调用;预览确认后创建或复用同用途服务客户端。
|
||||
2. 在 Gateway“系统设置 → 统一认证”填写一次性接入码和 Gateway 地址。Gateway 自动领取 Manifest 与机器凭据,并在验证候选 Runtime 时建立 SSF Stream。
|
||||
|
||||
Gateway 后端先把 machine Secret 写入 SecretStore,随后自动读取 Discovery、生成并托管 256 bit Push Bearer、创建 paused Stream、完成 Verification、首次启用 Stream,并进入 360 秒 RFC 7662 bootstrap。浏览器只在两端连接表单的短暂操作期间接触 machine Secret;Push Bearer 和 Secret 引用始终不可见,数据库、响应和日志不保存明文。管理员不编辑 Secret 文件,也不需要重启 Gateway。
|
||||
Gateway 后端先把 Machine Secret 写入 SecretStore,随后自动读取 Discovery、生成并托管 256 bit Push Bearer、创建 paused Stream、完成 Verification、首次启用 Stream,并进入 360 秒 RFC 7662 bootstrap。接入码和 Machine Secret 只从浏览器提交到 Gateway 服务端;Push Bearer 和 Secret 引用始终不可见,数据库、响应和日志不保存明文。管理员不编辑 Secret 文件,也不需要重启 Gateway。
|
||||
|
||||
环境前置配置只保留 OIDC 公共参数和 Gateway 公共地址:
|
||||
环境前置配置只保留 SecretStore 与运行时基础设施参数:
|
||||
|
||||
- `OIDC_ISSUER`、`OIDC_TENANT_ID`;
|
||||
- `AI_GATEWAY_PUBLIC_BASE_URL`,生产必须是认证中心可访问的 HTTPS 地址。
|
||||
- `IDENTITY_SECRET_STORE`、`IDENTITY_SECRET_DIR`,或对应 Kubernetes SecretStore 参数;
|
||||
- `IDENTITY_SECURITY_EVENTS_HEARTBEAT_INTERVAL_SECONDS`、`IDENTITY_SECURITY_EVENTS_STALE_AFTER_SECONDS` 和 `IDENTITY_SECURITY_EVENTS_CLOCK_SKEW_SECONDS`。
|
||||
|
||||
`OIDC_INTROSPECTION_CLIENT_ID/SECRET` 仅作为旧部署兼容回退,不再是新连接必填项。新连接把 machine 凭据动态托管到 SecretStore,OIDC fallback、SSF 管理 Token 和 Verification 共用这一份凭据,重启后继续生效。
|
||||
Issuer、Tenant、Gateway 公网地址和机器 Client 均来自 Active Revision,不读取旧 OIDC 环境变量。OIDC fallback、SSF 管理 Token 和 Verification 共用一份托管机器凭据,重启后继续生效。
|
||||
|
||||
第一版一个 Gateway 部署只允许一个认证中心连接。下游业务服务无需接入 SSF。
|
||||
|
||||
## SecretStore
|
||||
|
||||
本地和 Docker 使用 `file` 驱动。服务自动创建目录并强制目录 `0700`、文件 `0600`;Docker Compose 将目录放在持久化 `api_data` 卷中。用户不写入任何 `ssf-delivery-*` 文件。
|
||||
本地和 Docker 使用 `file` 驱动。服务自动创建目录并强制目录 `0700`、文件 `0600`;Docker Compose 将目录放在持久化 `api_data` 卷中。用户不写入任何 Secret 文件。
|
||||
|
||||
Kubernetes 使用 `kubernetes` 驱动和一个部署时预创建的空 Secret:
|
||||
|
||||
```text
|
||||
OIDC_SECURITY_EVENTS_SECRET_STORE=kubernetes
|
||||
OIDC_SECURITY_EVENTS_KUBERNETES_NAMESPACE=easyai
|
||||
OIDC_SECURITY_EVENTS_KUBERNETES_SECRET_NAME=easyai-gateway-security-events
|
||||
IDENTITY_SECRET_STORE=kubernetes
|
||||
IDENTITY_KUBERNETES_NAMESPACE=easyai
|
||||
IDENTITY_KUBERNETES_SECRET_NAME=easyai-gateway-identity
|
||||
```
|
||||
|
||||
参考清单见 `deploy/kubernetes/security-events-secret-rbac.yaml`。ServiceAccount 只能对这个固定 Secret 执行 `get/update/patch`,不能创建、删除或读取其他 Secret。数据库、API、浏览器、日志和审计只保存或展示非敏感连接元数据。
|
||||
|
||||
@@ -8,7 +8,7 @@ Accepted,2026-07-17。
|
||||
|
||||
Gateway 是标准应用接入协议的首个消费方。认证中心保持消费方无关;“统一认证”页面、Gateway 本地租户映射、Legacy JWT 兼容和 Session 策略均属于 Gateway 自己的管理边界。
|
||||
|
||||
OIDC、JIT、Introspection、BFF 和 SSF 的业务配置以 Gateway 管理 API/数据库为唯一来源。数据库、SecretStore、Session 加密根、Bootstrap 管理凭据、TLS 与 RBAC 仍由部署环境提供。开发阶段不读取或迁移旧 `OIDC_*`、`VITE_OIDC_*` 业务变量,升级后由管理员重新配对。
|
||||
OIDC、JIT、Introspection、BFF 和 SSF 的业务配置以 Gateway 管理 API/数据库为唯一来源。数据库、SecretStore、Bootstrap 管理凭据、TLS 与 RBAC 仍由部署环境提供;Machine Credential 和 Session Encryption Key 由服务端生成或领取,只存入 SecretStore,Revision 仅保存引用。开发阶段不读取或迁移旧 `OIDC_*`、`VITE_OIDC_*` 业务变量,升级后由管理员重新配对。
|
||||
|
||||
## Revision 状态机
|
||||
|
||||
@@ -50,3 +50,17 @@ active -> superseded (回滚、替换或禁用)
|
||||
## 前端运行时配置
|
||||
|
||||
Web 前端启动后读取公开只读统一认证状态,不使用 `VITE_OIDC_*` 构建变量。安全事件作为统一认证能力状态显示,原独立页面只保留运行运维动作。
|
||||
|
||||
## 部署级配置
|
||||
|
||||
允许继续由部署环境提供的统一认证相关参数仅限 SecretStore 与基础设施健康窗口:
|
||||
|
||||
```dotenv
|
||||
IDENTITY_SECRET_STORE=file
|
||||
IDENTITY_SECRET_DIR=.local-secrets/identity
|
||||
IDENTITY_SECURITY_EVENTS_HEARTBEAT_INTERVAL_SECONDS=60
|
||||
IDENTITY_SECURITY_EVENTS_STALE_AFTER_SECONDS=180
|
||||
IDENTITY_SECURITY_EVENTS_CLOCK_SKEW_SECONDS=60
|
||||
```
|
||||
|
||||
Kubernetes 部署改用 `IDENTITY_KUBERNETES_NAMESPACE`、`IDENTITY_KUBERNETES_SECRET_NAME`、`IDENTITY_KUBERNETES_API_SERVER`、`IDENTITY_KUBERNETES_TOKEN_FILE` 和 `IDENTITY_KUBERNETES_CA_FILE`。这些参数不包含 Issuer、Audience、Scope、Client ID、Machine Secret 或业务开关。
|
||||
|
||||
Reference in New Issue
Block a user