Remove user-facing new-api naming; Docker/network/container names use heicode. Go imports updated; Dockerfiles and workflows ldflags fixed. Made-with: Cursor
151 lines
7.8 KiB
Markdown
151 lines
7.8 KiB
Markdown
# HeiCode 浏览器登录流程(客户端 ↔ Manager)
|
||
|
||
本文给出 Heicode 客户端通过浏览器完成 Manager 登录的端到端流程,并说明字段、错误模型与扩展点。当前实现以 **loopback 直接回 token** 为主,OAuth2 + PKCE 已在客户端预留。
|
||
|
||
> 代码位置:
|
||
>
|
||
> - 客户端:`cc-haha/src/server/api/heicode-auth.ts`
|
||
> - 服务端:`heicode/controller/heicode_oauth.go`、`heicode/router/heicode-router.go`
|
||
|
||
## 一、设计目标
|
||
|
||
- 用户启动 Heicode 客户端 → 看到登录卡片 → 点击「浏览器登录」
|
||
- 浏览器跳到 Manager 控制台,完成账号登录
|
||
- Manager 颁发 / 复用一条专用 Token,回跳客户端 loopback 地址
|
||
- 客户端落地 Token,激活 Provider,自动拉模型列表
|
||
|
||
整体不要求平台事先支持完整 OAuth2,loopback + token 即可工作;后续可平滑切换到 Authorization Code + PKCE。
|
||
|
||
## 二、参与方与端点
|
||
|
||
|
||
| 端点 | 谁实现 | 用途 |
|
||
| -------------------------------------- | ---------------- | ---------------------------------- |
|
||
| `POST /api/heicode-auth/oauth/start` | 客户端本地服务 | 生成 `state` / PKCE,返回 authorize URL |
|
||
| `GET /heicode/oauth/authorize` | Manager(heicode) | 校验 loopback、引导登录、回跳 token |
|
||
| `GET /heicode/oauth/session` | Manager(heicode) | 给「请先登录」过渡页轮询登录态 |
|
||
| `GET /api/heicode-auth/oauth/callback` | 客户端本地服务 | 接收 token / code,落地并激活 |
|
||
|
||
|
||
## 三、当前实现(loopback + token 直回)
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
autonumber
|
||
participant U as 用户
|
||
participant C as Heicode 客户端<br/>(本地 HTTP 服务)
|
||
participant B as 浏览器
|
||
participant M as Heicode Manager<br/>(heicode)
|
||
|
||
U->>C: 点击「浏览器登录」
|
||
C->>C: 生成 state / PKCE 并写入会话
|
||
C-->>B: 返回 authorize URL
|
||
B->>M: GET /heicode/oauth/authorize?state=...&redirect_uri=...&provider_id=...
|
||
alt 用户未登录
|
||
M-->>B: 渲染过渡页(链接到 /login)
|
||
loop 每 1.5s
|
||
B->>M: GET /heicode/oauth/session
|
||
M-->>B: { logged_in }
|
||
end
|
||
B->>M: 重新请求 authorize
|
||
end
|
||
M->>M: 校验 loopback redirect_uri
|
||
M->>M: 取或新建名为 "HeiCode" 的 Token
|
||
M-->>B: 302 redirect_uri?state=...&token=sk-XXXX
|
||
B->>C: GET /api/heicode-auth/oauth/callback?token=...&state=...
|
||
C->>C: 校验 state、激活 Provider、拉模型
|
||
C-->>B: 返回成功页(用户可关闭浏览器)
|
||
```
|
||
|
||
|
||
|
||
### 关键校验
|
||
|
||
- `state` 与 `redirect_uri` 必填,`redirect_uri` 必须是 loopback 主机:`127.0.0.1` / `localhost` / `::1`
|
||
- 客户端会话过期(默认 5 分钟)后回调直接判失败
|
||
- 客户端默认从 `?token=` / `?access_token=` / `?apiKey=` / `?apikey=` 任一字段读取 Token
|
||
|
||
### 字段表
|
||
|
||
|
||
| 名称 | 在 | 说明 |
|
||
| ------------------------------------------ | --------- | --------------------------------------------------- |
|
||
| `state` | URL query | 客户端生成的不可猜测随机串,回跳时校验 |
|
||
| `redirect_uri` | URL query | 必须是 loopback;Manager 会拒绝其它主机 |
|
||
| `provider_id` | URL query | `taijiaicloud` / `clawdrouter`;用于客户端识别落到哪个 provider |
|
||
| `token` | 回跳 query | Manager 颁发的 HeiCode 专用 Token,前缀 `sk-` |
|
||
| `code` / `code_verifier` | 标准 OAuth | 当前 loopback 模式不使用;启用 PKCE 时必需 |
|
||
| `code_challenge` / `code_challenge_method` | URL query | 启用 PKCE 时由客户端附带,方法固定 `S256` |
|
||
| `client_id` / `scope` | URL query | 启用 PKCE 时附带,分别来自客户端环境变量 |
|
||
|
||
|
||
## 四、扩展形态:标准 OAuth2 + PKCE
|
||
|
||
当平台具备 token 端点后,仅需在客户端配置环境变量即可启用:
|
||
|
||
|
||
| 变量 | 用途 |
|
||
| ---------------------------------------- | ----------------------------------------- |
|
||
| `HEICODE_<PROVIDER>_OAUTH_AUTHORIZE_URL` | 自定义 authorize 端点 |
|
||
| `HEICODE_<PROVIDER>_OAUTH_TOKEN_URL` | code → access_token 交换端点 |
|
||
| `HEICODE_<PROVIDER>_OAUTH_CLIENT_ID` | OAuth Client ID(启用 PKCE 时必需) |
|
||
| `HEICODE_<PROVIDER>_OAUTH_SCOPE` | 申请的 scope,例如 `models:read,messages:write` |
|
||
|
||
|
||
详见 `[../onboarding/env-variables.md](../onboarding/env-variables.md)`。
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant C as 客户端
|
||
participant B as 浏览器
|
||
participant P as 平台 Authorize
|
||
participant T as 平台 Token
|
||
|
||
C->>B: authorize URL?response_type=code&client_id&...&code_challenge
|
||
B->>P: 用户登录授权
|
||
P-->>B: 302 redirect_uri?code=&state=
|
||
B->>C: callback?code=&state=
|
||
C->>T: POST /token { grant_type=authorization_code, code, code_verifier, ... }
|
||
T-->>C: { access_token }
|
||
C->>C: 激活 Provider 并拉模型
|
||
```
|
||
|
||
|
||
|
||
## 五、错误模型
|
||
|
||
|
||
| 触发 | HTTP / 行为 | 客户端展示 |
|
||
| --------------------------- | ----------------------------------------------------- | -------------------------- |
|
||
| `state` / `redirect_uri` 缺失 | Manager 400 | 浏览器停留报错 |
|
||
| `redirect_uri` 非 loopback | Manager 400 `redirect_uri must be a loopback address` | 检查客户端配置 |
|
||
| 用户未登录 | Manager 渲染过渡页并轮询 session | 浏览器停留并自动跳转 |
|
||
| 客户端会话过期 | 客户端 callback 返回错误页 | 提示「登录会话已过期,请回到 HeiCode 重试」 |
|
||
| 平台未配置 token 端点但只回了 code | 客户端 callback 错误页 | 提示「平台未配置 token 交换端点」 |
|
||
| Provider 模型校验失败 | 客户端 400 | 拉模型异常或返回空集 |
|
||
|
||
|
||
## 六、与 Agnet API 设计的衔接
|
||
|
||
- 这里的 Token 用于 Heicode 客户端调 Manager;Manager 调 Agnet 时使用 `[./agnet-platform-api-design.md](./agnet-platform-api-design.md)` §2.1 / §2.2 中的 M2M JWT 或用户委派令牌
|
||
- 跨链路追踪建议在 Manager 调 Agnet 时附带 `X-Heicode-Correlation-Id` 与本登录会话关联
|
||
|
||
## 七、安全注意事项
|
||
|
||
- 客户端必须在每次启动时 **新生成** `state` / `code_verifier`,禁止复用
|
||
- Manager 必须 **拒绝** 非 loopback 的 `redirect_uri`(已实现)
|
||
- Token 长生命周期使用前提:Manager 端可吊销且具备审计;不要在跨设备粘贴中传播
|
||
- 出现安全事件时,Manager 应能批量吊销名为 `HeiCode` 的 Token
|
||
|
||
## 八、界面截图(docs/images)
|
||
|
||
> 下列截图来自 `docs/images/`,用于辅助理解登录链路与界面落位。
|
||
|
||

|
||

|
||

|
||

|
||

|
||

|
||
|