跳转到内容

身份验证

本页说明人如何登录 OpenBot,以及程序如何调用 API。 一个人在浏览器中登录一次。然后这个人为脚本和服务创建用户令牌。

调用 /v1 下的业务路由有两种方式:

方式 谁使用 发送什么
用户令牌 脚本、后端服务、机器人 Authorization: Bearer <token>
Session cookie 运行在 OpenBot 源(origin)上的浏览器客户端 __Host-openbot-session cookie

两种方式在每次调用时都需要权限。见 权限。


登录

OpenBot 不保存密码。它使用 OpenID Connect 提供方。OpenID Connect(OIDC)是一种标准方式,让另一个服务来确认一个人的身份。 提供方有两种:

  • 平台提供方为整个平台的人提供登录。由平台管理员设置。见 设置平台提供方。
  • SSO 连接是某一个组织的提供方。邮箱属于该组织已验证域名的人,通过它登录。见 SSO 和域名。

要开始登录,你的客户端从 OpenBot 源发送这个请求:

Terminal window
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 路由

OpenBot 使用 Better Auth 处理登录。Better Auth 在 /auth/* 下提供自己的路由,做法和它的 Effect 指南 一样。这些路由不在 API 参考中。Better Auth 文档 描述了它们。

你仍然可以直接使用它们。平台提供方的提供方 ID 是 oidc,回调地址是 /auth/callback/oidc。SSO 连接用自己的 ID 作为提供方 ID,它的回调地址是 /auth/callback/<connectionId>。

Terminal window
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。

设置平台提供方

在你的提供方那里,把 OpenBot 注册为一个客户端。重定向 URI 使用 <publicOrigin>/auth/callback/oidc。OpenBot 会请求 openid profile email 这几个 scope(权限范围)。

然后把提供方告诉 OpenBot。在新平台上,设置程序通过 --oidc-issuer、--oidc-client-id 和 --oidc-client-secret 完成这件事。之后,平台管理员用 PATCH /v1/platform/settings 修改它。见 Platform。

设置 值
identityProvider.issuer issuer URL,例如 https://id.example.com。必须是 HTTPS,末尾不能有斜杠。
identityProvider.clientId 提供方给出的 client ID。
identityProvider.clientSecret client secret。如果是公共客户端,就不要填。
publicOrigin OpenBot 的公开 HTTPS 源,例如 https://api.example.com。

没有 client secret 时,OpenBot 作为公共客户端,使用 PKCE 登录。PKCE 是一种检查,用来保护登录代码。 平台也可以完全没有提供方。这时人们只能通过 SSO 连接登录。

开发账户

开发服务器(devenv shell -- pnpm dev)使用一个本地测试账户,不使用提供方。这个账户是 developer@localhost.test,它是平台管理员。 只有开发入口提供这个账户。生产程序从不提供。见 配置。

下面的命令会登录,并把 cookie 保存到文件中:

Terminal window
curl -c cookies.txt -X POST https://localhost:8443/auth/development/sign-in \
-H "Origin: https://localhost:8443" \
-H "Content-Type: application/json" \
-d '{}'

读取和结束登录

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 会检查它属于哪里:

  1. 如果某个组织验证了该账户已验证邮箱的域名,并且允许 joinByDomain,账户就加入这个组织。
  2. 如果账户是通过 SSO 连接登录的,它就加入该 SSO 连接所属的组织。
  3. 如果账户仍然没有组织,并且平台允许任何人创建组织,它会得到一个名为 “Personal” 的新组织。它是那里的 Super Administrator(超级管理员)。
  4. 否则它没有组织。这时组织路由会返回 403 和 MembershipRequired。

OpenBot 在每个带 session cookie 的请求上也会做这些检查。见 组织。

被暂停的成员使用 cookie 时,会得到 403 和 MembershipRequired。他们的令牌会立即失效,并得到 401 和 AuthenticationRequired。

选择组织

带 session cookie 的请求必须说明它在哪个组织中执行。在 OpenBot-Organization 请求头中发送组织 ID:

Terminal window
curl -b cookies.txt \
-H "OpenBot-Organization: org_8f3a" \
https://api.example.com/v1/sessions
  • 没有这个请求头时,OpenBot 使用你唯一的活跃组织。
  • 如果你有多个活跃组织,又没有发送这个请求头,OpenBot 返回 400 和 OrganizationRequired。

用户令牌只属于一个组织。它会忽略这个请求头。


登录后,浏览器持有 cookie __Host-openbot-session。它带有 Secure、HttpOnly 和 SameSite=Lax。

  • 一次登录有效 30 天。
  • 使用满一天后,OpenBot 会续期它。

Origin 规则

浏览器的每个请求都会带上 cookie,即使请求来自其他网站。所以 OpenBot 会检查写操作来自哪里。 使用 cookie 时,每个 POST、PUT、PATCH 和 DELETE 请求都必须发送 Origin 请求头。 这个请求头必须和 平台设置 中的 publicOrigin 完全相同。如果不同,OpenBot 返回 403 和 ForbiddenOrigin。

Terminal window
curl -b cookies.txt \
-H "Origin: https://localhost:8443" \
-H "Content-Type: application/json" \
-d '{"title":"Notes"}' \
https://localhost:8443/v1/sessions

使用用户令牌的请求不需要 Origin 请求头。


用户令牌

用户令牌让程序代表你执行操作。令牌能做的事永远不会超过你能做的事。它还可以有自己的策略,从而做得更少。见 权限。

你可以用 session cookie 管理令牌,也可以用带有 tokens.write 权限的令牌管理。没有策略的令牌不能管理令牌。

令牌属于一个组织:也就是创建它的那个请求所在的组织。使用 cookie 时,发送 OpenBot-Organization 请求头来选择组织。见 选择组织。

完整的数据结构见 User tokens 参考。

创建令牌

Terminal window
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 之间的整数。不填时,令牌一直有效,直到你撤销它。
policies 可选。用来限制令牌的策略。不填时,允许你能做的所有事,但 tokens.read 和 tokens.write 除外。

OpenBot 返回 201:

{
"token": {
"id": "5f0c2a8e-7d1b-4c3e-9a55-2b6f1e8d4c10",
"name": "CI bot",
"prefix": "obut_Xr4pQ2aL",
"policies": [
{
"effect": "allow",
"permissionGroups": [
"responses.run",
"sessions.read",
"sessions.write"
],
"resources": ["openbot.org.{org}"]
}
],
"createdAt": "2026-10-20T09:00:00.000Z",
"expiresAt": "2027-01-18T09:00:00.000Z",
"lastUsedAt": null
},
"secret": "obut_Xr4pQ2aL..."
}

每个 secret 都以 obut_ 开头,所以泄露的令牌很容易被发现。prefix 是前 13 个字符。用它来区分你的令牌。

列出令牌

Terminal window
curl -b cookies.txt https://api.example.com/v1/user/tokens

回答是 { "items": [ ... ] },最早的排在前面。列表中从不包含 secret。 lastUsedAt 最多每分钟更新一次。过期的令牌会留在列表中,直到你撤销它们。

撤销令牌

Terminal window
curl -X DELETE -b cookies.txt \
-H "Origin: https://api.example.com" \
https://api.example.com/v1/user/tokens/5f0c2a8e-7d1b-4c3e-9a55-2b6f1e8d4c10

OpenBot 返回 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。

限制和错误

状态码 错误 何时出现
400 TokenPolicyInvalid 某个策略指定了你的组织或 openbot.platform 之外的资源。
401 AuthenticationRequired 没有有效的 cookie 或令牌。
403 PermissionDenied 调用者没有 tokens.read 或 tokens.write。
403 ForbiddenOrigin 使用 cookie 写入,但没有完全相同的 Origin 请求头。
404 TokenNotFound 你没有这个 ID 的令牌。
409 TokenLimitReached 你已经有 25 个令牌。请求体中有 "limit": 25。
503 TokenStorageUnavailable OpenBot 无法连接到它的数据库。

一个成员同时最多持有 25 个令牌。过期的令牌也计算在内,所以请撤销旧令牌来腾出空间。


使用令牌

在任何 /v1 路由上,都在 Authorization 请求头中发送令牌:

Terminal window
curl -H "Authorization: Bearer $OPENBOT_TOKEN" \
https://api.example.com/v1/sessions

已撤销、已过期或未知的令牌会得到 401 和 AuthenticationRequired。如果 OpenBot 无法检查令牌,它返回 503 和 AuthenticationUnavailable。

你自己的空间

在组织内,每个成员都有自己的 Sessions、Apps 和连接。你的令牌和 cookie 只能看到你自己的内容。 如果你请求另一个成员的 Session,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>。