Files
heicode-win/docs/integration/heicode-oauth-flow.md
T
gongzhiyong 1f21309597 refactor: rename manager codebase dir new-api → heicode, module github.com/heicode/manager
Remove user-facing new-api naming; Docker/network/container names use heicode.
Go imports updated; Dockerfiles and workflows ldflags fixed.

Made-with: Cursor
2026-05-01 01:47:23 +08:00

151 lines
7.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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/`,用于辅助理解登录链路与界面落位。
![Heicode login flow screenshot 01](../images/wecom-screenshot-01.jpg)
![Heicode login flow screenshot 02](../images/wecom-screenshot-02.jpg)
![Heicode login flow screenshot 03](../images/wecom-screenshot-03.jpg)
![Heicode login flow screenshot 04](../images/wecom-screenshot-04.jpg)
![Heicode login flow screenshot 05](../images/wecom-screenshot-05.jpg)
![Heicode login flow screenshot 06](../images/wecom-screenshot-06.jpg)