Skip to content

认证

外脑编辑器 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 SessionBearer <supabase-jwt> 或后端兼容用户 access token前端用户会话用户页面、团队管理、支付/订阅等浏览器业务端点
API KeyBearer wn-xxx外部自动化/API 调用与消费归因/api/released-app/*, ROMP 会话/消息、显式允许的运行时端点
Schedule TokenBearer <schedule-jwt>定时任务内部触发/api/released-app/*
OAuth TokenBearer wno-xxx第三方应用 / 官方移动端/api/released-app/*, /oauth/userinfo, mobile:full 白名单业务接口
Agent TokenBearer wna-xxxAgent 绑定主体Agent 专用端点与显式授权的运行时端点
Device TokenBearer <device-token>设备心跳 / ACME / 本地一体机/device/*

1. User Session 认证

前端用户会话可以来自 Supabase Auth JWT,也可以来自后端签发的兼容用户 access token。后端路由清单中的 authType: 'jwt' 表示 User Session 语义,不表示必须使用旧的 Supabase-only jwtAuth 中间件。

使用方式

bash
curl -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  https://block2-api.wainao.chat/my/account

验证流程

  1. 用户态业务路由挂 userSessionAuth
  2. userSessionAuth 复用 combinedAuth 的 JWT 分支,兼容 Supabase JWT 与后端本地 access token
  3. API Key、Agent Token、Schedule Token、Device Token 等非用户会话凭证会被拒绝

认证上下文

typescript
{
  method: 'jwt',
  userId: string,        // 用户 ID(JWT payload.sub)
  user: {
    id: string,
    email: string,
    role: string,
    user_metadata: object,
    app_metadata: object,
  }
}

错误响应

状态码错误说明
401Missing or invalid authorization header缺少或格式错误的 Authorization 头
401Token expiredJWT 已过期
401Invalid token无效的 JWT
401JWT authentication failedJWT 验证失败

2. API Key 认证

wn- 前缀标识的 API Key,用于外部程序调用。

获取 API Key

在项目设置中创建 API Key,系统会生成 wn-xxx 格式的密钥。

使用方式

bash
curl -H "Authorization: Bearer wn-your-api-key" \
  https://block2-api.wainao.chat/api/released-app/DEPLOYMENT_ID/run \
  -d '{"inputs": {"text": "hello"}}'

验证流程

  1. 对 API Key 进行 SHA-256 哈希
  2. api_keys 表中查找匹配记录
  3. 检查 Key 是否已被撤销(deleted_atrevoked_at 任一非空即拒绝)
  4. 检查 Key 是否已过期(expires_at 非空且早于当前时间即拒绝)
  5. 检查额度限制(limit_credits vs usage_credits
  6. 异步更新 last_used_at 时间戳

验证逻辑由 authenticateApiKey() 共享函数统一实现,apiKeyAuthcombinedAuth 两个中间件均调用此函数,确保行为一致。

端点白名单

通过 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 时也幂等返回成功。

认证上下文

typescript
{
  method: 'api-key',
  apiKeyId: string,   // API Key 记录 ID
  teamId: string,     // 所属团队 ID
  userId: string,     // Key 创建者的用户 ID
}

错误响应

状态码错误说明
401Invalid API keyKey 不存在
401API key has been revokedKey 已被撤销(deleted_atrevoked_at 非空)
401API key has expiredKey 已过期(expires_at 早于当前时间)
401Authentication failed认证过程中发生内部错误
403API key credit limit exceededKey 额度已用尽
403API key is not allowed for this endpointKey 不可访问该端点
429Too many requests, please try again later超出限流阈值(per-key 600/min)

3. Schedule Token 认证

系统内部生成的短时 JWT,用于定时任务触发 API 运行。

使用场景

定时任务调度器在触发执行时,自动生成包含 schedule_idteam_iddeployment_id 等信息的短时 JWT。该 Token 仅用于 /api/released-app/* 路径。

认证上下文

typescript
{
  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 中间件,仅挂到明确允许的路由上。

使用方式

bash
curl -H "Authorization: Bearer wno-your-access-token" \
  https://block2-api.wainao.chat/api/released-app/r/my-app/v1/chat/completions

认证上下文

typescript
{
  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/ensurePOST /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

AI Workflow Editor