跳至主要内容

取得 access_token

取得應用級憑證 access_token。第三方應用後端使用 client_credentials 模式換取令牌,用於呼叫成員、組織架構、企業資訊及機器人等開放介面。

介面資訊​

項目說明
介面名稱取得 access_token
請求方式POST
請求地址https://{gateway_host}/auth/v1/oauth/token
資料格式application/json
鑑權方式無(使用應用憑證換取)
跨域支援瀏覽器跨域;不返回 Access-Control-Allow-Credentials。App Secret 仍不得下發到瀏覽器

前置條件​

  1. 應用已在管理後臺「內部應用」中建立並發布。
  2. 已在應用詳情「憑證與基本資訊」中取得 AppId(即 client_id)和 AppSecret(即 client_secret)。
  3. AppSecret 僅保存在應用後端,嚴禁下發至前端或客戶端。

請求參數​

請求標頭​

請求標頭必填說明
Content-Type是固定為 application/json

請求體​

{
"client_id": "app_10001",
"client_secret": "link_xxxxxxxxx",
"grant_type": "client_credentials"
}
參數類型必填說明
client_idstring是應用 AppId
client_secretstring是應用 AppSecret
grant_typestring是授權類型,固定為 client_credentials

回應參數​

成功回應(OAuth 標準 JSON 外殼,不含平臺 {code,msg,data} 包裝):

{
"access_token": "opaque-app-access-token",
"expires_in": 7200
}
欄位類型說明
access_tokenstring應用級憑證令牌,預設有效期 7200 秒(2 小時)
expires_ininteger憑證剩餘有效期,單位:秒

令牌使用規則​

  1. 重用與快取:access_token 在有效期內可重複使用,建議應用後端集中快取,並提前(例如剩餘 5 分鐘時)自動刷新,避免頻繁請求本介面。
  2. 憑證隔離:access_token 是應用級憑證,不是使用者登入態;不得放入 Cookie、不得下發給客戶端,也不能作為業務系統自身的 Bearer Token。
  3. Secret 輪換:應用管理員在後臺輪換 AppSecret 後,舊密鑰簽發的所有 access_token 立即失效,需重新請求本介面取得新令牌。
  4. 攜帶方式:呼叫開放介面時,推薦透過請求標頭 Authorization: Bearer <access_token> 攜帶;部分介面也支援 Query 參數 ?access_token=<access_token>。

錯誤碼說明​

換取令牌失敗時,使用 HTTP 狀態碼與 OAuth error 欄位返回:

{
"error": "INVALID_CLIENT",
"error_description": "invalid client credentials"
}
HTTP 狀態碼error 錯誤碼含義與排查建議
400INVALID_REQUEST請求格式不是合法 JSON、grant_type 不為 client_credentials,或缺少必填欄位
401INVALID_CLIENT應用不存在、已停用/刪除,或 client_id 與 client_secret 不匹配
500SERVER_ERROR服務端異常,請稍後重試

多語言呼叫範例​

以下範例在服務端執行;應用密鑰和應用令牌不得下發到客戶端。

Shell​

curl -sS -X POST "https://{gateway_host}/auth/v1/oauth/token" \
-H "Content-Type: application/json" \
-d '{"client_id":"app_10001","client_secret":"link_xxxxxxxxx","grant_type":"client_credentials"}'

PHP​

<?php
// 生產環境應檢查 HTTP 狀態碼和回應體,再映射業務錯誤。
$handle = curl_init('https://{gateway_host}/auth/v1/oauth/token');
curl_setopt_array($handle, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_POSTFIELDS => '{"client_id":"app_10001","client_secret":"link_xxxxxxxxx","grant_type":"client_credentials"}',
CURLOPT_RETURNTRANSFER => true,
]);
echo curl_exec($handle);
curl_close($handle);

Golang​

package main

import ("bytes"; "net/http")

func main() {
// 令牌只在服務端請求中使用,並按介面約定攜帶。
request, _ := http.NewRequest(http.MethodPost, "https://{gateway_host}/auth/v1/oauth/token", bytes.NewBufferString(`{"client_id":"app_10001","client_secret":"link_xxxxxxxxx","grant_type":"client_credentials"}`))
request.Header.Set("Content-Type", "application/json")
response, _ := http.DefaultClient.Do(request)
defer response.Body.Close()
}

C++​

#include <curl/curl.h>

int main() {
// 生產環境應啟用 TLS 校驗並處理 HTTP 錯誤。
CURL* handle = curl_easy_init();
struct curl_slist* headers = nullptr;
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(handle, CURLOPT_URL, "https://{gateway_host}/auth/v1/oauth/token");
curl_easy_setopt(handle, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(handle, CURLOPT_POSTFIELDS, R"({"client_id":"app_10001","client_secret":"link_xxxxxxxxx","grant_type":"client_credentials"})");
const CURLcode result = curl_easy_perform(handle);
curl_slist_free_all(headers); curl_easy_cleanup(handle);
return result == CURLE_OK ? 0 : 1;
}