鑑權與 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
在控制檯建立應用時(包括註冊時自動建立的 demo 應用),系統會生成第一組憑據,請儲存到服務端的金鑰管理系統中。Client ID 和 Client Secret 可以在控制檯概覽的“接入憑證”中檢視,檢視 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 頻道身份
獨立 RTC 頻道的介面使用不同的身份:
| 身份 | 用於 |
|---|---|
| App Token | 頻道管理、簽發票據、移出和封禁成員 |
| User Token | 使用者本人的頻道會話:加入、心跳、續發憑據、退出 |
你的服務端只把使用者自己的頻道票據交給他,不要交出 App Token。頻道票據和媒體憑據都不能代替 IM 的登入令牌,客戶端也不能指定別人的使用者名稱或角色。
