AgnesCode 认证与授权协议分析报告
协议端点: 桌面应用 ↔ 浏览器 ↔ Agnes Auth Server ↔ Agnes API
通信方式: OAuth2 + Deep Link + HTTPS REST
报告日期: 2026-07-25
分析版本: v1.0.17
1. 认证体系总览
AgnesCode 存在两套独立的认证体系:
1.1 OAuth2 用户认证 (AgnesCode 桌面端)
用于 AgnesCode 桌面应用的用户登录, 获取 access_token, 调用 Agnes BFF API。
流程: 浏览器 OAuth 登录 → Deep Link 回调 → Code Exchange → access_token
用途: 调用 AgnesCode BFF API (api-agnes-code.agnes-ai.com)
Token 格式: JWT / 不透明令牌 (非 sk- 开头)1.2 API Key 认证 (Agnes 开发者平台)
用于 platform.agnes-ai.com 开发者平台的 API 访问。
流程: 在 platform.agnes-ai.com/settings/apiKeys 创建
用途: 调用 Agnes 开发者 API (端点待确认)
Token 格式: sk-... (OpenAI 兼容格式)注意: 这两套体系不互通。API Key 不能用于 AgnesCode BFF API。
2. OAuth2 认证流程 (完整版)
2.1 流程总图
┌──────────────┐ ┌──────────────┐ ┌──────────────────┐
│ Desktop App │ │ 浏览器 │ │ Agnes Auth │
│ (Electron) │ │ (Chrome) │ │ Server │
└──────┬───────┘ └──────┬───────┘ └────────┬─────────┘
│ │ │
│ 1. 生成 32B state │ │
│ │ │
│ 2. 构建登录 URL │ │
│ https://app.agnes-ai.com/login │
│ ?client=agnes-code │
│ &redirect_uri=agnes://auth/callback │
│ &state={state} │
│ │ │
│ 3. shell.openExternal │ │
├───────────────────────►│ │
│ │ │
│ 4. 用户输入账号密码 │ │
│ ├──── POST /login ─────────►│
│ │◄─── 302 Redirect ────────┤
│ │ agnes://auth/callback │
│ │ ?code={auth_code} │
│ │ &state={state} │
│ │ │
│ 5. 操作系统处理 │ │
│ agnes:// 协议 │ │
│◄───────────────────────┤ │
│ │ │
│ 6. 验证 state 匹配 │ │
│ │ │
│ 7. POST /api/v1/code │ │
│ /auth/exchange-code │ │
├──────────────────────────────────────────────────►│
│◄──────────────────────────────────────────────────┤
│ { access_token, user_info } │
│ │ │
│ 8. 保存 token │ │
│ localStorage │ │
│ + Keychain │ │2.2 关键参数
| 参数 | 值 | 说明 |
|---|---|---|
| 登录页面 | https://app.agnes-ai.com/login | 从 .env 提取 |
| Client ID | agnes-code | 固定值 |
| Redirect URI | agnes://auth/callback | Deep Link 协议 |
| State 长度 | 32 字节 (64 hex) | 随机生成 |
| Code 交换端点 | POST /api/v1/code/auth/exchange-code | BFF API |
| Token 存储 | localStorage + 系统密钥链 | - |
2.3 登录 URL 构造
javascript
function buildLoginUrl(state) {
const loginUrl = process.env.AGNES_SA_WEB_LOGIN_URL || "https://app.agnes-ai.com/";
const url = new URL("/login", loginUrl);
url.searchParams.set("client", "agnes-code");
url.searchParams.set("redirect_uri", "agnes://auth/callback");
url.searchParams.set("state", state);
return url.toString();
}2.4 Code Exchange
请求:
POST https://api-agnes-code.agnes-ai.com/v1/api/v1/code/auth/exchange-code
Content-Type: application/json
{
"code": "auth_code_from_callback",
"redirect_uri": "agnes://auth/callback",
"state": "32_byte_hex_state",
"client_id": "agnes-code"
}成功响应:
json
{
"code": 0,
"data": {
"access_token": "jwt_token",
"user_info": {
"id": "user_id",
"name": "User Name",
"email": "user@example.com"
}
}
}错误响应:
json
{
"code": "000501",
"message": "Login expired",
"data": { "trace_id": "xxx" }
}2.5 Token 使用
javascript
// 调用 BFF API
fetch("https://api-agnes-code.agnes-ai.com/v1/models", {
headers: {
"Authorization": "Bearer {access_token}",
"X-App-Id": "1",
"X-Platform": "1"
}
});3. API Key 认证 (开发者平台)
3.1 获取方式
在 https://platform.agnes-ai.com/settings/apiKeys 页面创建 API Key。
3.2 Token 格式
- 格式:
sk-...(OpenAI 兼容格式) - 示例:
sk-FbuJ0X6Ugwemgcm2Tl4eiSgmv9NhcDi2p8Kr3oVG6AKoYjK9
3.3 使用方式 (待确认)
测试发现:
api.agnes-ai.com→ 返回000201 Resource not foundapi-agnes-code.agnes-ai.com→ 返回000501 Login expired(需要 OAuth token)platform.agnes-ai.com→ Next.js SPA, 无 API 端点
结论: 开发者平台的 API Key 的准确使用方式需要查阅 platform 站点的文档或 UI 说明。
4. 两种认证方式的对比
| 特性 | OAuth2 (AgnesCode) | API Key (Platform) |
|---|---|---|
| 获取方式 | 浏览器登录 + OAuth 流程 | 在 platform 后台创建 |
| Token 格式 | JWT / 不透明令牌 | sk- 开头 |
| 适用 API | AgnesCode BFF | Agnes 开发者 API (待确认) |
| 有效期 | 有限 (需刷新) | 长期 |
| 用途 | 桌面应用用户认证 | 开发者程序化访问 |
5. Token 管理与生命周期
5.1 Token 存储
javascript
// 渲染进程 (localStorage)
localStorage.setItem("token", access_token);
localStorage.setItem("userinfo", JSON.stringify(user_info));
// 主进程 (系统密钥链)
// macOS: Keychain (com.agnes.code.secrets)
// Windows: Credential Manager
// Linux: libsecret5.2 Token 刷新
当前代码中未发现自动刷新机制。当 API 返回 401 时, 自动清除 token 并触发登出:
javascript
// 401 处理 (防抖 2 秒)
let debounce = false;
function handle401(response) {
if (response.status !== 401 || debounce) return;
debounce = true;
localStorage.removeItem("token");
localStorage.removeItem("userinfo");
setTimeout(() => { debounce = false; }, 2000);
}5.3 登出
javascript
function logout() {
localStorage.removeItem("token");
localStorage.removeItem("userinfo");
localStorage.removeItem("userPptData");
window.dispatchEvent(new CustomEvent('agnes:userinfo-updated'));
}6. 安全机制
| 机制 | 说明 |
|---|---|
| CSRF 防护 | 32 字节随机 state, 回调时验证精确匹配 |
| 超时 | 登录流程 60 秒超时 |
| 防重放 | 同一 code+state 组合只处理一次 |
| 密钥隔离 | OAuth token 和 API Key 存储在不同位置 |
7. 程序化认证方案
7.1 方案一: 手动 Code 粘贴 (推荐)
1. 生成登录链接, 发给用户
2. 用户在浏览器中打开并登录
3. 用户从浏览器地址栏复制 code 参数
4. 调用 exchange-code API 获取 access_token
5. 使用 access_token 调用 AgnesCode BFF API7.2 方案二: 本地回调服务器
1. 启动本地 HTTP 服务器 (localhost:随机端口)
2. 构造登录 URL, redirect_uri 指向本地服务器
3. 用户登录后, 浏览器重定向到本地服务器
4. 本地服务器接收 code, 交换 token7.3 方案三: 开发者 API Key
1. 在 platform.agnes-ai.com 创建 API Key
2. 使用 API Key 直接调用 API
3. 注意: 此方式只能调用开发者 API, 不能用于 AgnesCode BFF8. 已知的 API 端点
8.1 AgnesCode BFF API
| 端点 | 方法 | 认证 | 说明 |
|---|---|---|---|
/api/v1/code/auth/exchange-code | POST | 无 (code+state) | 交换授权码 |
/v1/models | GET | Bearer Token | 模型列表 |
/v1/chat/completions | POST | Bearer Token | 聊天补全 |
/api/v2/subscription/credits-balance | GET | Bearer Token | 信用余额 |
/api/v1/subscription/credits-transactions | POST | Bearer Token | 交易记录 |
8.2 开发者 API (待确认)
| 端点 | 方法 | 认证 | 说明 |
|---|---|---|---|
| 待确认 | - | API Key (sk-) | 需要查阅 platform 文档 |
9. 当前状态
Phase 1: 账号注册 ✅ 已完成 (用户已注册)
Phase 1: OAuth 登录 ❌ 未完成 (需要用户配合)
Phase 1: API Key ❌ 未确认 (sk- 格式的 API key 不适用于 AgnesCode BFF)
需要的下一步:
1. 用户完成一次 OAuth 登录, 获取 access_token
2. 或确认 API Key 的正确使用方式
3. 之后才能继续 Phase 2/3 的开发和测试