Appearance
免登与鉴权
组织应用有两层凭证,分别解决"你的后端是谁"和"当前是哪个用户在用"。
时序图
┌─────────┐ 1.点「打开」 ┌──────────┐ 2.POST /api/orgs/{org}/apps/{app}/auth-code
│ 客户端 │ ─────────────→ │ 应用窗口壳 │ ────────────────────────→ 机灵兔服务端
│ 主窗口 │ │(机灵兔的代码)│ ←──────── {auth_code}
└─────────┘ └────┬─────┘
│ 3. iframe.src = 你的页面URL#jlt_auth_code=..&jlt_org_id=..&jlt_app_id=..
┌────▼─────┐ 4. 页面把 auth_code 发给自己的后端
│ 你的页面 │
└────┬─────┘
┌────▼─────┐ 5. POST /api/open/auth/token (app_key+app_secret)
│ 你的后端 │ 6. POST /api/open/auth/user (auth_code)
└──────────┘ ← {user_id, nickname, avatar_url, org_id, org_name, org_role, team_ids}两层凭证
| 凭证 | 谁持有 | 换取方式 | 有效期 | 用途 |
|---|---|---|---|---|
app_key / app_secret | 你的后端(长期保存) | 应用创建时颁发,可轮换 | 长期 | 换 app access token |
| app access token | 你的后端 | POST /api/open/auth/token | 2 小时 | 调用其余开放 API |
| 一次性授权码(authCode) | 你的页面 → 你的后端 | 客户端打开应用时拼在 URL 上;也可用 JSAPI requestAuthCode() 重新获取 | 5 分钟、只能用一次 | 换用户身份 |
app_secret 只能放在服务器
app_secret 一旦泄露到页面/客户端代码,任何人都能拿它换 app access token 调用你被授予的所有能力(包括代表你的应用发消息、消耗你组织的 AI 额度)。 如果怀疑泄露,立即在应用设置里「轮换密钥」,旧密钥会即时失效。
换 app access token
POST /api/open/auth/token
Content-Type: application/json
{ "app_key": "oak_xxx", "app_secret": "xxx" }json
{ "access_token": "xxx", "token_type": "Bearer", "expires_in": 7200 }token 有效期 2 小时,请缓存并在过期前刷新(例如提前 1 分钟),不要每次 请求都重新换取——同一个 app_key 的换取频率限制是 20 次/分钟。
换用户身份
POST /api/open/auth/user
Authorization: Bearer <app access token>
Content-Type: application/json
{ "auth_code": "..." }返回:
json
{
"user_id": "u_123",
"nickname": "张三",
"avatar_url": "https://...",
"org_id": "org_abc",
"org_name": "锥鹏科技",
"org_role": "member",
"team_ids": ["team_1", "team_2"]
}拿到这个身份后,请在你自己的应用里建立会话(cookie/session 等,跟机灵兔的 登录态完全独立)。org_id/org_role 是打开应用当下所在的组织上下文—— 自建应用固定是应用所属组织;被其他组织安装的应用,这里是安装方组织。
⚠️ 多组织开发建议:同一个应用可能同时被多个组织自建/安装(也可能同一个用户 属于多个组织,分别从不同组织打开你的应用)。请以每次换到的
org_id作为你 自己数据模型的分区键,不要假设"反正只有一个组织"而把用户会话/数据写死在全局作 用域里;后续调用org/members/im/send等接口时也要显式带上这个org_id(缺省值是 你自己的家/发布方组织,不会自动推断成这次打开它的安装方组织,详见 Open API)。org_name仅供展示用,不要当作分区键——组织可以改名,org_id不变。
authCode 是一次性的:换过一次、或超过 5 分钟,就返回 400,让页面用 jlt.requestAuthCode() 重新取一枚新码再试。用完建议顺手把 URL 上的 jlt_auth_code 参数清掉(history.replaceState),避免用户刷新页面时拿旧码 重试。
免登参数放在 URL fragment(#…)里(2026-08-27 起,桌面/移动壳同口径): fragment 不随请求发给服务器、不进访问日志、不被 Referer 带出。页面用 location.hash 解析(SDK 的 parseLaunchParams() 已兼容 fragment 与旧版 query 两种形态)。应用地址自带 fragment 时参数以 & 追加在其后。
常见错误
| HTTP 状态 | 含义 |
|---|---|
| 400 | authCode 无效 / 已使用过 / 已过期(取新码重试) |
| 401 | app token 缺失/无效/过期;app_key/app_secret 不正确;密钥已被轮换;应用已停用或组织已解散 |
| 402 | 调用 AI 能力时,应用所属组织尚未开通钱包 |
| 403 | 这项能力没有被授予(错误信息会提示找谁开) |
| 429 | 触发了限流,稍后重试 |