认证
外脑编辑器 API 按主体区分认证方式,所有认证信息通过 Authorization 请求头传递。
源码: apps/backend/src/middleware/combined-auth.ts, apps/backend/src/middleware/api-key-auth.ts, apps/backend/src/middleware/oauth-auth.ts
认证方式总览
| 方式 | Token 格式 | 适用场景 | 适用端点 |
|---|---|---|---|
| User Session | Bearer <supabase-jwt> 或后端兼容用户 access token | 前端用户会话 | 用户页面、团队管理、支付/订阅等浏览器业务端点 |
| API Key | Bearer wn-xxx | 外部自动化/API 调用与消费归因 | /api/released-app/*, ROMP 会话/消息、显式允许的运行时端点 |
| Schedule Token | Bearer <schedule-jwt> | 定时任务内部触发 | /api/released-app/* |
| OAuth Token | Bearer wno-xxx | 第三方应用 / 官方移动端 | /api/released-app/*, /oauth/userinfo, mobile:full 白名单业务接口 |
| Agent Token | Bearer wna-xxx | Agent 绑定主体 | Agent 专用端点与显式授权的运行时端点 |
| Device Token | Bearer <device-token> | 设备心跳 / ACME / 本地一体机 | /device/* |
1. User Session 认证
前端用户会话可以来自 Supabase Auth JWT,也可以来自后端签发的兼容用户 access token。后端路由清单中的 authType: 'jwt' 表示 User Session 语义,不表示必须使用旧的 Supabase-only jwtAuth 中间件。
使用方式
curl -H "Authorization: Bearer YOUR_JWT_TOKEN" \
https://block2-api.wainao.chat/my/account验证流程
- 用户态业务路由挂
userSessionAuth userSessionAuth复用combinedAuth的 JWT 分支,兼容 Supabase JWT 与后端本地 access token- API Key、Agent Token、Schedule Token、Device Token 等非用户会话凭证会被拒绝
认证上下文
{
method: 'jwt',
userId: string, // 用户 ID(JWT payload.sub)
user: {
id: string,
email: string,
role: string,
user_metadata: object,
app_metadata: object,
}
}错误响应
| 状态码 | 错误 | 说明 |
|---|---|---|
| 401 | Missing or invalid authorization header | 缺少或格式错误的 Authorization 头 |
| 401 | Token expired | JWT 已过期 |
| 401 | Invalid token | 无效的 JWT |
| 401 | JWT authentication failed | JWT 验证失败 |
2. API Key 认证
以 wn- 前缀标识的 API Key,用于外部程序调用。
获取 API Key
在项目设置中创建 API Key,系统会生成 wn-xxx 格式的密钥。
使用方式
curl -H "Authorization: Bearer wn-your-api-key" \
https://block2-api.wainao.chat/api/released-app/DEPLOYMENT_ID/run \
-d '{"inputs": {"text": "hello"}}'验证流程
- 对 API Key 进行 SHA-256 哈希
- 在
api_keys表中查找匹配记录 - 检查 Key 是否已被撤销(
deleted_at或revoked_at任一非空即拒绝) - 检查 Key 是否已过期(
expires_at非空且早于当前时间即拒绝) - 检查额度限制(
limit_creditsvsusage_credits) - 异步更新
last_used_at时间戳
验证逻辑由
authenticateApiKey()共享函数统一实现,apiKeyAuth和combinedAuth两个中间件均调用此函数,确保行为一致。
端点白名单
通过 combinedAuth 中间件的 API Key 仅允许访问显式授权的自动化/运行时端点。普通用户页面 API 默认拒绝 API Key,避免把 API Key 误用为网页登录身份。
通过 apiKeyAuth 中间件的 API Key(/api/released-app/*)无路径限制。
管理 API Key
浏览器端只通过 User Session 调用后端 REST 接口管理 API Key,不再直连 Supabase api_keys 表或删除 RPC。
| 方法 | 路径 | 权限 | 说明 |
|---|---|---|---|
GET | /teams/:teamId/api-keys | 团队成员 | 列出未撤销、非系统用途 API Key,只返回脱敏字段 |
POST | /teams/:teamId/api-keys | 团队 owner | 创建 API Key;明文 key 只在响应中返回一次 |
PATCH | /teams/:teamId/api-keys/:keyId | 团队 owner | 更新名称和额度限制 |
DELETE | /teams/:teamId/api-keys/:keyId | 团队 owner | 软删除 API Key,保留审计可追溯性 |
GET /teams/:teamId/api-keys
列出团队中未撤销、非系统用途的 API Key;只返回脱敏标识、名称、额度和审计字段。
PATCH /teams/:teamId/api-keys/:keyId
团队 owner 更新 API Key 名称、描述或额度限制,不会重新返回密钥明文。
DELETE /teams/:teamId/api-keys/:keyId
团队 owner 软删除 API Key;删除后立即不可用于认证,记录仍保留以供审计。
网页端 User Session
以下端点使用 refresh token 本身作为凭据,不要求 Authorization 请求头。
POST /auth/session/refresh
请求体为 { "refreshToken": "..." }。成功后轮换 refresh token,并返回新的网页端 session;无效、过期或已消费的 token 返回 401。
POST /auth/session/revoke
请求体为 { "refreshToken": "..." }。登出时吊销 refresh token;未提供 token 时也幂等返回成功。
认证上下文
{
method: 'api-key',
apiKeyId: string, // API Key 记录 ID
teamId: string, // 所属团队 ID
userId: string, // Key 创建者的用户 ID
}错误响应
| 状态码 | 错误 | 说明 |
|---|---|---|
| 401 | Invalid API key | Key 不存在 |
| 401 | API key has been revoked | Key 已被撤销(deleted_at 或 revoked_at 非空) |
| 401 | API key has expired | Key 已过期(expires_at 早于当前时间) |
| 401 | Authentication failed | 认证过程中发生内部错误 |
| 403 | API key credit limit exceeded | Key 额度已用尽 |
| 403 | API key is not allowed for this endpoint | Key 不可访问该端点 |
| 429 | Too many requests, please try again later | 超出限流阈值(per-key 600/min) |
3. Schedule Token 认证
系统内部生成的短时 JWT,用于定时任务触发 API 运行。
使用场景
定时任务调度器在触发执行时,自动生成包含 schedule_id、team_id、deployment_id 等信息的短时 JWT。该 Token 仅用于 /api/released-app/* 路径。
认证上下文
{
method: 'schedule',
scheduleId: string, // 定时任务 ID
teamId: string, // 所属团队 ID
userId: string, // 空字符串(Schedule 无关联用户)
deploymentId: string, // 目标部署 ID
}安全限制
- Schedule Token 会验证请求的
deploymentId是否与 Token 中声明的一致,防止越权执行
4. OAuth Token 认证
通过 OAuth 2.0 Authorization Code + PKCE 流程获取的 access_token,用于第三方应用。
注意:OAuth Token 认证不通过全局 combinedAuth,而是使用 route-local 的 oauthAuth 中间件,仅挂到明确允许的路由上。
使用方式
curl -H "Authorization: Bearer wno-your-access-token" \
https://block2-api.wainao.chat/api/released-app/r/my-app/v1/chat/completions认证上下文
{
method: 'oauth',
userId: string, // 授权用户 ID
appId: string, // OAuth App ID
scopes: string[], // 授权的 scope 列表
}Scope 限制
OAuth Token 只能访问 scope 对应的路由。当前支持的 scope:
| Scope | 允许的路由 |
|---|---|
chat:completions | /api/released-app/* |
mobile:full | 移动端业务白名单:profile、devices、账号绑定、POST /my/default-project/ensure、POST /storage/:projectId/upload、ROMP、push、/services/passthrough/* 等 |
访问未授权路由返回 403 insufficient_scope。
获取 Token
详见 OAuth 2.0 API。
安全建议
- 浏览器用户页面使用 User Session,不使用 API Key
- 永远不要在客户端代码中暴露 API Key
- 定期轮换 API Key
- 使用环境变量存储密钥
- 为 API Key 设置合理的额度限制
- 第三方应用优先使用 OAuth 2.0 而非直接暴露 API Key
实现视角的中间件选型、撤销机制、错误码详解见 /dev/token-types。