鉴权与 App Token
服务端 REST API(下文简称 OpenAPI)只供你的业务服务端调用。调用前先用应用的 Client ID 和 Client Secret 换取 App Token,之后每个请求都在 Authorization 请求头中带上它:
Authorization: Bearer <App Token>App Token 代表整个应用的管理权限:可以创建和删除用户、以任何用户的身份发消息、导出消息。请只在服务端保存和使用,不要下发到 App、网页或小程序中。
不要在浏览器中调用 OpenAPI
OpenAPI 不返回跨域响应头,浏览器中的脚本无法直接调用。客户端(App、网页)请使用用户自己的 User Token 访问客户端接口,见登录与登录设备。
获取 Client ID 和 Client Secret
在控制台创建应用时,系统会生成第一组凭据,Client Secret 只显示这一次,请立即保存到服务端的密钥管理系统中。之后可以在应用详情的“服务端密钥”页面轮换或吊销凭据,见服务端凭据与 IP 白名单。
每个应用最多同时有两个有效的 Secret(主、备两个槽位),用于不停机轮换:
- 在控制台轮换密钥,生成新的 Secret,旧 Secret 进入 24 小时的宽限期,期间新旧 Secret 都可以使用;
- 把服务端的配置更新为新的 Secret,用它换取新的 App Token;
- 宽限期结束后旧 Secret 自动失效,或在确认无误后手动吊销。
Secret 被吊销或过期后,它换取的 App Token 立即失效。
换取 App Token
/{org_name}/{app_name}/token用应用的凭据换取 App Token。这个接口不需要 Authorization 请求头。
路径参数
| 参数 | 类型 | 说明 |
|---|---|---|
org_name | String | 租户的唯一标识,即 AppKey 中 # 之前的部分 |
app_name | String | 应用名称,即 AppKey 中 # 之后的部分 |
请求体
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
grant_type | String | 是 | 固定为 client_credentials |
client_id | String | 是 | 应用的 Client ID |
client_secret | String | 是 | 应用的 Client Secret |
请求示例
curl -X POST "$IM_API/$ORG/$APP/token" \
-H "Content-Type: application/json" \
-d '{
"grant_type": "client_credentials",
"client_id": "YXA6MVMEOd4cqtAvTUnGUUCnTw",
"client_secret": "YXA6sMvoBP0HiVoT-69b1BWXzip5_-Ii2ea8u0ph9ijVgck"
}'响应
成功返回 200 OK:
| 字段 | 类型 | 说明 |
|---|---|---|
access_token | String | App Token |
expires_in | Number | 有效期,单位为秒。默认 604800(7 天),由应用的运行策略 app_token_ttl_seconds 决定,可设 300 秒到 1 年 |
application | String | 应用 ID |
{
"access_token": "eyJhbGciOiJFZERTQSIsImtpZCI6ImsxIiwidHlwIjoiSldUIn0.eyJpc3Mi...",
"expires_in": 604800,
"application": "99579846509723648"
}错误
| HTTP 状态码 | code | 说明 |
|---|---|---|
| 400 | invalid_argument | grant_type 不是 client_credentials |
| 401 | invalid_client | Client ID 或 Client Secret 错误,或者 org_name、app_name 不存在。为防止探测,这几种情况不作区分 |
| 403 | ip_not_allowed | 来源 IP 不在应用的 IP 白名单内 |
| 403 | tenant_unavailable | 租户已暂停或处于注销冷静期 |
| 403 | app_unavailable | 应用已停用或被暂停服务 |
| 429 | rate_limited | 请求过于频繁,按 Retry-After 响应头等待后重试。每个来源 IP 每分钟最多换取 120 次;凭据校验通过后,这次换取还计入应用的 OpenAPI 调用额度 |
使用和缓存 App Token
使用 Go、Python 或 Node.js 的服务端 SDK 时,SDK 会自动换取、缓存和续期 App Token,下面的规则已经替你处理。
- 缓存并复用:App Token 在有效期内可以反复使用,不要每次调用 OpenAPI 前都重新换取。建议在服务端缓存,在到期前(例如剩余不到 10%)提前换取新的。多个服务实例可以各自换取,同一时间有多个有效的 App Token 不会互相影响。
- 失效后重新换取:调用 OpenAPI 返回
401 unauthenticated时,说明 App Token 已经失效,重新换取一次后重试。以下情况会让已签发的 App Token 提前失效:- 签发它的 Secret 被吊销或过期;
- 应用被停用、被平台暂停服务,或租户被暂停;
- 应用被删除、租户已注销,这时
details.reason为app_deleted或tenant_closed,不要再重试,请清除保存的凭据。
{
"error": {
"code": "unauthenticated",
"message": "App Token 无效或已过期",
"request_id": "HQ566J6O5VSPRLYPUX5UXOEJIX"
}
}每个请求的鉴权检查
每个 OpenAPI 请求依次经过以下检查,任何一项不通过都直接返回错误:
| 顺序 | 检查 | 不通过时 |
|---|---|---|
| 1 | App Token 的签名和有效期,签发它的 Secret 仍然有效,租户和应用没有让令牌失效的变化 | 401 unauthenticated |
| 2 | App Token 所属的应用与路径中的 org_name、app_name 一致 | 403 permission_denied |
| 3 | 来源 IP 在应用的 IP 白名单内(没有设置白名单时不限制) | 403 ip_not_allowed |
| 4 | 租户和应用可以提供服务。令牌签发之后应用被停用、暂停服务或租户被暂停的,令牌随即失效,在第 1 步就返回 401 | 403 tenant_unavailable 或 403 app_unavailable |
| 5 | 应用的 OpenAPI 调用额度(每秒请求数)没有用完 | 429 rate_limited |
通过检查后,请求才进入具体的业务处理。各接口自己的错误见对应的文档,通用错误见错误码。
安全建议
- 只在服务端保存凭据:Client Secret 和 App Token 等同于应用的管理员密码,不要写进客户端代码、不要提交到代码仓库,日志中也不要打印。
- 开启 IP 白名单:把业务服务端的出口 IP 加入IP 白名单,即使凭据泄露,其他地方也无法调用。
- 定期轮换 Secret:按上文的步骤轮换,不会中断服务。怀疑泄露时立即在控制台吊销,它换取的 App Token 随即失效。
- 测试和生产分开:为测试环境和生产环境创建不同的应用,各自使用自己的凭据。
RTC 频道身份
App Token 用于频道管理、票据授权和成员处置;User Token 用于本人频道会话。业务服务端只给客户端交付其自己的频道票据,不交付 App Token。频道票据、媒体凭据都不能代替 IM 身份令牌,客户端不能自行指定别人的用户名或角色。
