身份验证
面向接入 OpenBot 客户端或扩展服务端的开发者。示例需要本页说明的访问权限。从开发者手册开始。
本页说明人如何登录 OpenBot,以及程序如何调用 API。一个人在浏览器中登录一次。然后这个人为脚本和服务创建用户令牌。
调用 /v1 下的业务路由有两种方式:
| 方式 | 谁使用 | 发送什么 |
|---|---|---|
| 用户令牌 | 脚本、后端服务、机器人 | Authorization: Bearer <token> |
| Session cookie | 运行在 OpenBot 源(origin)上的浏览器客户端 | __Host-openbot-session cookie |
两种方式在每次调用时都需要权限。见 权限。
OpenBot 不保存密码。它使用 OpenID Connect 提供方。OpenID Connect(OIDC)是一种标准方式,让另一个服务来确认一个人的身份。提供方有两种:
要开始登录,你的客户端从 OpenBot 源发送这个请求:
curl -X POST https://api.example.com/auth/sign-in \ -H "Origin: https://api.example.com" \ -H "Content-Type: application/json" \ -d '{"email":"ada@example.com","returnTo":"/settings/keys"}'{ "url": "https://id.example.com/authorize?..." }两个字段都是可选的。OpenBot 根据 email
的域名选择提供方。如果该域名有 SSO 连接,url
就指向它。否则指向平台提供方。如果两者都没有,OpenBot 返回 503 和
SignInUnavailable。
把浏览器跳转到这个
url。这个回答还会设置登录状态 cookie。这个人登录后,提供方把浏览器送回 OpenBot。OpenBot 设置 session
cookie,然后把浏览器跳转到 returnTo。见
返回路径。如果登录失败,浏览器会跳转到
/auth/error?error=<code>,并且不会得到 cookie。
Better Auth 路由
Section titled “Better Auth 路由”OpenBot 使用 Better Auth 处理登录。Better Auth 在
/auth/* 下提供自己的路由,做法和它的
Effect 指南
一样。这些路由不在 API 参考中。Better Auth 文档
描述了它们。
你仍然可以直接使用它们。平台提供方的提供方 ID 是 oidc,回调地址是
/auth/callback/oidc。SSO 连接用自己的 ID 作为提供方 ID,它的回调地址是
/auth/callback/<connectionId>。
curl -X POST https://api.example.com/auth/sign-in/social \ -H "Origin: https://api.example.com" \ -H "Content-Type: application/json" \ -d '{ "provider": "oidc", "callbackURL": "https://api.example.com/settings/keys" }'callbackURL 必须在 OpenBot 源上。如果不在,Better Auth 返回 403。
设置平台提供方
Section titled “设置平台提供方”由平台运维人员配置身份提供方。参见 配置登录.
开发服务器(devenv shell -- pnpm dev)使用一个本地测试账户,不使用提供方。这个账户是
developer@localhost.test,它是平台管理员。只有开发入口提供这个账户。生产程序从不提供。见
配置。
下面的命令会登录,并把 cookie 保存到文件中:
curl -c cookies.txt -X POST http://localhost/auth/development/sign-in \ -H "Origin: http://localhost" \ -H "Content-Type: application/json" \ -d '{}'读取和结束登录
Section titled “读取和结束登录”GET /auth/session 返回已登录的账户和它的组织。它需要 session cookie。
{ "userId": "u_123", "profile": { "name": "Ada", "email": "ada@example.com", "emailVerified": true }, "memberships": [ { "organizationId": "org_8f3a", "name": "Example", "status": "active", "roles": ["member"] } ], "platformAdmin": false, "expiresAt": "2026-11-19T10:00:00.000Z"}| 字段 | 含义 |
|---|---|
memberships |
账户所在的组织,以及它在每个组织中的状态和角色。 |
platformAdmin |
账户是平台管理员时为 true。这时它可以使用 /v1/platform。见 Platform。 |
POST /auth/sign-out 结束登录。这是一个 Better
Auth 路由。发送一个 JSON 请求体({})和 Origin 请求头(见下文)。它返回
200。
一个平台有很多组织。用户和组织是分开的。一个账户可以创建组织,也可以是多个组织的成员。账户登录时,OpenBot 会检查它属于哪里:
- 如果某个组织验证了该账户已验证邮箱的域名,并且允许
joinByDomain,账户就加入这个组织。 - 如果账户是通过 SSO 连接登录的,它就加入该 SSO 连接所属的组织。
- OpenBot 不会为它创建组织。没有组织时,组织路由会返回
403和MembershipRequired。账户仍然可以创建组织或接受邀请。
OpenBot 在每个带 session cookie 的请求上也会做这些检查。见 组织。
被暂停的成员使用 cookie 时,会得到 403 和
MembershipRequired。他们的令牌会立即失效,并得到 401 和
AuthenticationRequired。
带 session cookie 的请求必须说明它在哪个组织中执行。在 OpenBot-Organization
请求头中发送组织 ID:
curl -b cookies.txt \ -H "OpenBot-Organization: org_8f3a" \ https://api.example.com/v1/chats- 没有这个请求头时,OpenBot 使用你唯一的活跃组织。
- 如果你有多个活跃组织,又没有发送这个请求头,OpenBot 返回
400和OrganizationRequired。
用户令牌只属于一个组织。它会忽略这个请求头。
Session cookie
Section titled “Session cookie”登录后,浏览器持有 cookie __Host-openbot-session。它带有 Secure、HttpOnly
和 SameSite=Lax。
- 一次登录有效 30 天。
- 使用满一天后,OpenBot 会续期它。
Origin 规则
Section titled “Origin 规则”浏览器的每个请求都会带上 cookie,即使请求来自其他网站。所以 OpenBot 会检查写操作来自哪里。使用 cookie 时,每个
POST、PUT、PATCH 和 DELETE 请求都必须发送 Origin
请求头。这个请求头必须和 平台设置 中的
publicOrigin 完全相同。如果不同,OpenBot 返回 403 和 ForbiddenOrigin。
curl -b cookies.txt \ -H "Origin: http://localhost" \ -H "Content-Type: application/json" \ -d '{"input":"Hello"}' \ http://localhost/v1/bots/$BOT/messages使用用户令牌的请求不需要 Origin 请求头。
用户令牌让程序代表你执行操作。令牌能做的事永远不会超过你能做的事。它还可以有自己的策略,从而做得更少。见 权限。
你可以用 session cookie 管理令牌,也可以用可以对 Token 做 write
的令牌管理。没有策略的令牌不能管理令牌。
令牌属于一个组织:也就是创建它的那个请求所在的组织。使用 cookie 时,发送
OpenBot-Organization 请求头来选择组织。见 选择组织。
完整的数据结构见 User tokens 参考。
curl -b cookies.txt \ -H "Origin: https://api.example.com" \ -H "Content-Type: application/json" \ -d '{"name":"CI bot","expiresInDays":90}' \ https://api.example.com/v1/user/tokens| 字段 | 规则 |
|---|---|
name |
必填。去掉首尾空格后,长度为 1 到 80 个字符。 |
expiresInDays |
可选。1 到 365 之间的整数。不填时,令牌一直有效,直到你撤销它。 |
policy |
可选。用来限制令牌的一个策略。不填时,允许你能做的所有事,但对 Token 和 Platform 的操作除外。 |
OpenBot 返回 201:
{ "token": { "id": "5f0c2a8e-7d1b-4c3e-9a55-2b6f1e8d4c10", "name": "CI bot", "prefix": "obut_Xr4pQ2aL", "policy": "{\"_tag\":\"Rules\",\"algorithm\":\"denyOverrides\",\"rules\":[{\"_tag\":\"Allow\",\"actions\":[\"*\"],\"resources\":[\"Chat\",\"File\",\"Request\",\"...\",\"Budget\"]}]}", "createdAt": "2026-10-20T09:00:00.000Z", "expiresAt": "2027-01-18T09:00:00.000Z", "lastUsedAt": null }, "secret": "obut_Xr4pQ2aL..."}每个 secret 都以 obut_ 开头,所以泄露的令牌很容易被发现。prefix
是前 13 个字符。用它来区分你的令牌。
curl -b cookies.txt https://api.example.com/v1/user/tokens回答是 { "items": [ ... ] },最早的排在前面。列表中从不包含 secret。
lastUsedAt 最多每分钟更新一次。过期的令牌会留在列表中,直到你撤销它们。
使用列表中令牌的 UUID id。旧 v4 和新 v7
ID 都可使用。API 会在访问存储前拒绝非 UUID 格式的 ID。
curl -X DELETE -b cookies.txt \ -H "Origin: https://api.example.com" \ https://api.example.com/v1/user/tokens/5f0c2a8e-7d1b-4c3e-9a55-2b6f1e8d4c10OpenBot 返回 204 并删除这个令牌。令牌会立即失效。
GET /v1/tokens/verify
显示调用者是谁。对于令牌,它还显示令牌本身和它的策略。所有调用者都可以使用它。
{ "caller": { "kind": "user_token", "userId": "u_123", "organizationId": "org_8f3a", "tokenId": "5f0c2a8e-7d1b-4c3e-9a55-2b6f1e8d4c10" }, "token": { "id": "5f0c2a8e-7d1b-4c3e-9a55-2b6f1e8d4c10", "name": "CI bot" }}使用 session cookie 时,caller.kind 是 member,token 是 null。
| 状态码 | 错误 | 何时出现 |
|---|---|---|
401 |
AuthenticationRequired |
没有有效的 cookie 或令牌。 |
403 |
Forbidden |
调用者不能对 Token 做 read 或 write。 |
403 |
ForbiddenOrigin |
使用 cookie 写入,但没有完全相同的 Origin 请求头。 |
404 |
TokenNotFound |
你没有这个 ID 的令牌。 |
409 |
TokenLimitReached |
你已经有 25 个令牌。请求体中有 "limit": 25。 |
503 |
TokenStorageUnavailable |
OpenBot 无法连接到它的数据库。 |
一个成员同时最多持有 25 个令牌。过期的令牌也计算在内,所以请撤销旧令牌来腾出空间。
在任何 /v1 路由上,都在 Authorization 请求头中发送令牌:
curl -H "Authorization: Bearer $OPENBOT_TOKEN" \ https://api.example.com/v1/chats已撤销、已过期或未知的令牌会得到 401 和
AuthenticationRequired。如果 OpenBot 无法检查令牌,它返回 503 和
AuthenticationUnavailable。
你自己的空间
Section titled “你自己的空间”在组织内,每个成员都有自己的 Chats、Apps 和连接。你的令牌和 cookie 只能看到你自己的内容。如果你请求另一个成员的 Chat,OpenBot 会返回
404,就像它不存在一样。
有些流程在一次往返之后,会把浏览器送回你的客户端。你用 returnTo
选择返回的位置。
返回路径必须是同一个源上的路径。它必须以一个 / 开头。它不能指向
/auth/*、/v1/* 或 /development/*,因为这些路径归 OpenBot 所有。默认值是
/。
OpenBot 没有页面,所以你的客户端必须提供这些路径。有两个流程会添加查询参数:
- App 授权。
当 App 登录返回、并且这个人已经登录时,OpenBot 会完成这个流程。浏览器会跳转到返回路径,并带上
?authorization=<flowId>。你的客户端可以用GET /v1/app-authorizations/<flowId>读取结果。如果这个人没有登录,浏览器会跳转到/?authorization=<flowId>。你的客户端用POST /auth/sign-in让这个人登录(见 登录),并把这个地址作为returnTo。然后它调用POST /v1/app-authorizations/<flowId>/complete来完成流程。 - 开发者测试。 开发者测试授权会返回到
/?developerTest=<testId>。
回调会提交持久命令,并保留原始调用人和 token 限制。完成请求接受
{ "commandKey" },返回 HTTP 202。读取流程的
executionId,再用执行 API 观察或取消。GET /v1/app-authorization-actions/:executionId
返回安全结果。令牌交换结果未知时等待决策;浏览器断开不会取消执行。