Skip to content

OAuth 2.0 ​

小雅开放平台使用授权码流程,让第三方智能体获得当前用户明确授权的最小权限。OAuth 只是授权层;实际访问 Personal 或 Team 资源时,服务端仍会重新校验用户、智能体、Scope、Team 成员状态和上下文版本。

授权入口 ​

http
GET /oauth/authorize

常用参数:

参数说明
response_type=code当前只使用授权码响应
client_id开放平台登记的客户端 ID
redirect_uri必须与登记的精确地址一致
scope空格分隔的最小权限集合
state主动浏览器授权流程必须生成并校验
code_challenge公共客户端使用 PKCE S256
code_challenge_method=S256不接受弱化的 PKCE 算法
team_idTeam 授权时显式指定精确 Team

完整浏览器跳转示例:

text
https://claw.zhenhuiai.com/oauth/authorize?response_type=code&client_id=agent-client&redirect_uri=https%3A%2F%2Fagent.example.com%2Foauth%2Fcallback&scope=profile%20balance%20model&state=<random-state>&code_challenge=<s256-challenge>&code_challenge_method=S256

授权成功后,平台重定向至登记回调:

text
https://agent.example.com/oauth/callback?code=<single-use-code>&state=<same-state>

小雅 App 的“点击打开”流程会直接生成一次性 Code 并附加到已登记入口。Code 只有 5 分钟有效且只能消费一次。回调页面在交换完成前不得渲染第三方资源,并应立即 303 跳转到不含 Code 的干净 URL。

Scope ​

Scope能力
profile当前授权用户以及可见 Team 上下文
balancePersonal 或精确 Team 余额
charge主动扣费与退款
usage当前智能体在 Personal 上下文的归因用量
modelPersonal 或 Team 可用模型目录与模型网关
team_readTeam 只读访问
team_manageTeam Owner/Admin 管理能力
skill已授权运行时 Skill/MCP 资产
sandbox云沙箱运行时

默认 Scope 仍是:

text
profile balance charge usage

默认值不包含 model、team_read 或 team_manage。需要模型或 Team 的客户端必须显式申请,不能依赖默认值。

Token 生命周期 ​

  • 授权码:5 分钟、单次消费;
  • 新授权码交换的 Access Token:7 天;已有 Token 保持原到期时间,开发者会话不得超过返回的 expires_in;
  • 新流程不签发 Refresh Token;
  • 历史 Refresh Token 只作为兼容路径继续轮换;
  • 用户、智能体、成员、角色、Team 状态或上下文版本变化会使旧凭证失效。

交换 Access Token ​

机密服务端客户端使用 client_secret;公共客户端不保存 Secret,必须提交创建授权请求时对应的 code_verifier。

bash
curl --request POST 'https://claw.zhenhuiai.com/oauth/token' \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'grant_type=authorization_code' \
  --data-urlencode 'client_id=agent-client' \
  --data-urlencode 'client_secret=<server-only-secret>' \
  --data-urlencode 'code=<single-use-code>' \
  --data-urlencode 'redirect_uri=https://agent.example.com/oauth/callback'

Node.js 服务端示例:

js
const body = new URLSearchParams({
  grant_type: 'authorization_code',
  client_id: process.env.XIAOYA_CLIENT_ID,
  client_secret: process.env.XIAOYA_CLIENT_SECRET,
  code,
  redirect_uri: 'https://agent.example.com/oauth/callback'
});

const response = await fetch('https://claw.zhenhuiai.com/oauth/token', {
  method: 'POST',
  headers: { Accept: 'application/json', 'Content-Type': 'application/x-www-form-urlencoded' },
  body,
  redirect: 'error',
  signal: AbortSignal.timeout(10_000)
});
const token = await response.json();
if (!response.ok) throw new Error(`OAuth failed: ${token.error}`);

Personal Token 成功响应:

json
{
  "access_token": "<server-only-token>",
  "token_type": "Bearer",
  "expires_in": 604800,
  "scope": "profile balance charge usage model"
}

Team Token 还会返回绑定信息:

json
{
  "access_token": "<server-only-team-token>",
  "token_type": "Bearer",
  "expires_in": 604800,
  "scope": "profile balance model team_read",
  "team_id": "team_01",
  "team_authorization_id": "authorization_01"
}
字段含义
access_token仅可信服务端保存并放入 Bearer Header 的凭证
token_type固定为 Bearer
expires_in从签发时刻起的有效秒数,当前为 604800
scope实际获准的空格分隔 Scope;不能假设等于申请值
team_id仅 Team Token 返回,表示唯一绑定 Team
team_authorization_id仅 Team Token 返回,表示可撤销的 Team 授权记录

失败响应遵循 OAuth 错误格式,不使用平台 success/data envelope:

json
{
  "error": "invalid_grant",
  "error_description": "Authorization code is invalid or expired"
}

常见 error 为 invalid_client、invalid_grant 和 unsupported_grant_type。不要向最终用户展示包含凭据或内部细节的原始错误描述。

撤销 Token ​

退出登录、解除绑定或检测到服务端会话风险时撤销 Token:

bash
curl --request POST 'https://claw.zhenhuiai.com/oauth/revoke' \
  --header 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'client_id=agent-client' \
  --data-urlencode 'client_secret=<server-only-secret>' \
  --data-urlencode 'token=<access-token>' \
  --data-urlencode 'token_type_hint=access_token'

成功撤销返回 HTTP 200;即使 Token 已失效,客户端也应清除自己的服务端 Session,不得继续尝试使用旧 Token。

Personal 与 Team 隔离 ​

Personal Token 与 Team Token 必须分别保存,并至少按以下维度建立服务端会话键:

text
client_id + user_subject + context_type + team_id

Team Token 绑定精确 Team,不能访问另一个 Team;Team Token 也不能调用 Personal 余额或用量接口。Personal Token 访问 Team 受保护资源会被拒绝。

服务端安全要求 ​

  • Access Token、Client Secret 和 Code 只保存在可信服务端;
  • 浏览器只保存智能体自己的 HttpOnly; Secure; SameSite=Lax Session Cookie;
  • Token 请求设置明确超时并禁止重定向;
  • Code 交换结果未知时不要盲目重试,重新发起授权;
  • 回调和 Token 响应使用 Cache-Control: no-store;
  • 不把 Token、Code 或秘密放进 URL、Prompt、日志、错误详情和前端存储。

全部 OAuth 参数与响应 Schema 见完整 API 参考。

OAuth credentials and model-provider secrets must remain on trusted servers.