造物工坊 · Foundry Core

共享后端的第一版提供 Google 登录。各项目通过同一个 HTTPS API 登录,在私有 PostgreSQL 的认证库中维护独立账号和会话。项目业务库可分别配置独立的数据库和角色。

服务端配置

  1. 在 Google Cloud 创建一个 Web application OAuth 客户端。授权重定向 URI 填写 https://<API 域名>/auth/google/callback。所有项目信任同一个客户端,因此共享 Google 同意页面的应用名称。
  2. 在服务器私网准备 PostgreSQL 13 或以上版本。在认证库执行一次 db/001-auth.sql(使用 psql -v ON_ERROR_STOP=1),给运行账号授予这四张表所需的查询及增删改权限。
  3. 按 .env.example 注入运行环境变量。每个项目配置一个固定的前端回调地址,本地开发可用 localhost。将 Google 客户端密钥和数据库连接串存入服务器的密钥管理设施。
  4. 由 Gitea Actions 在 ces-control 上使用 Go 1.25 构建并检查。部署工作流仅处理 main 上影响后端或部署的改动,将二进制启动在服务器 Docker 私网,由 Traefik 提供 HTTPS。通过 GET /healthz 检查进程,通过 GET /readyz 检查认证库。
  5. 代理避免记录 Google 回调的查询参数及认证请求头。设置入口限流,并定时删除三张临时表(oauth_attempts、login_grants、project_sessions)中 expires_at <= now() 的记录。

Actions 部署配置

在仓库的 Actions Secrets 配置 GOOGLE_CLIENT_ID 和 GOOGLE_CLIENT_SECRET,在 Actions Variables 配置 FOUNDRY_PROJECTS。变量值为 JSON 对象,例如 {"prompt":"http://localhost:17321/auth/callback"}。部署读取服务器上预先配置的 /opt/endoleap-infra/foundry/database.env,OAuth 值由 Actions 在启动容器时注入。

Google OAuth 的授权回调地址为 https://api.foundry.entroia.com/auth/google/callback。工作流会验证数据库就绪、匿名请求返回 401、Google 授权跳转参数和 HTTPS 就绪。完整登录还需在浏览器用 Google 测试账号走完回调、兑换和会话验证。

前端接入

  1. 在浏览器用 Web Crypto 生成 32 字节随机值,编码为无填充 Base64URL,作为 verifier 暂存在当前 tab 的 sessionStorage。对 verifier 字符串做 SHA-256 并用相同编码得到 challenge。
  2. 顶层导航到 GET /projects/<project>/auth/google?challenge=<challenge>。Google 回到共享 API 后,API 将浏览器重定向至已配置的项目回调。
  3. 回调页从 URL fragment 读取 code 或 error,用 history.replaceState 清掉 fragment。收到 code 时,向 POST /projects/<project>/auth/exchange 发送 X-Foundry-Code 和 X-Foundry-Verifier 请求头,随后清理暂存的 verifier。code 有效期一分钟,仅可使用一次。
  4. 将返回的八小时会话凭证保存在内存中,使用 Authorization: Bearer <access_token> 调用 GET /projects/<project>/auth/me。通过 POST /projects/<project>/auth/logout 撤销会话并清理本地凭证。刷新页面后,内存凭证需要通过重新登录获取。

同一个 Google 账号首次进入不同项目时,会分别创建用户 ID。会话绑定其签发项目。Google 账号的标识 sub 用于认领同一项目的既有账号,邮箱只作为资料字段。当前注册模式为开放注册。

验收

用同一个 Google 测试账号分别登录两个项目,确认用户 ID 不同。用 A 的会话请求 B 的 me 应返回 401。验证兑换码重放被拒绝,并确认退出 A 后 B 的会话仍有效。

S
Description
No description provided
Readme 1.2 MiB
Languages
Go 83.4%
PLpgSQL 7.5%
Shell 7.2%
Python 1.9%