取得 access_token
取得應用級憑證 access_token。第三方應用後端使用 client_credentials 模式換取令牌,用於呼叫成員、組織架構、企業資訊及機器人等開放介面。
介面資訊
| 項目 | 說明 |
|---|---|
| 介面名稱 | 取得 access_token |
| 請求方式 | POST |
| 請求地址 | https://{gateway_host}/auth/v1/oauth/token |
| 資料格式 | application/json |
| 鑑權方式 | 無(使用應用憑證換取) |
| 跨域 | 支援瀏覽器跨域;不返回 Access-Control-Allow-Credentials。App Secret 仍不得下發到瀏覽器 |
前置條件
- 應用已在管理後臺「內部應用」中建立並發布。
- 已在應用詳情「憑證與基本資訊」中取得
AppId(即client_id)和AppSecret(即client_secret)。 AppSecret僅保存在應用後端,嚴禁下發至前端或客戶端。
請求參數
請求標頭
| 請求標頭 | 必填 | 說明 |
|---|---|---|
Content-Type | 是 | 固定為 application/json |
請求體
{
"client_id": "app_10001",
"client_secret": "link_xxxxxxxxx",
"grant_type": "client_credentials"
}
| 參數 | 類型 | 必填 | 說明 |
|---|---|---|---|
client_id | string | 是 | 應用 AppId |
client_secret | string | 是 | 應用 AppSecret |
grant_type | string | 是 | 授權類型,固定為 client_credentials |
回應參數
成功回應(OAuth 標準 JSON 外殼,不含平臺 {code,msg,data} 包裝):
{
"access_token": "opaque-app-access-token",
"expires_in": 7200
}
| 欄位 | 類型 | 說明 |
|---|---|---|
access_token | string | 應用級憑證令牌,預設有效期 7200 秒(2 小時) |
expires_in | integer | 憑證剩餘有效期,單位:秒 |
令牌使用規則
- 重用與快取:
access_token在有效期內可重複使用,建議應用後端集中快取,並提前(例如剩餘 5 分鐘時)自動刷新,避免頻繁請求本介面。 - 憑證隔離:
access_token是應用級憑證,不是使用者登入態;不得放入 Cookie、不得下發給客戶端,也不能作為業務系統自身的 Bearer Token。 - Secret 輪換:應用管理員在後臺輪換
AppSecret後,舊密鑰簽發的所有access_token立即失效,需重新請求本介面取得新令牌。 - 攜帶方式:呼叫開放介面時,推薦透過請求標頭
Authorization: Bearer <access_token>攜帶;部分介面也支援 Query 參數?access_token=<access_token>。
錯誤碼說明
換取令牌失敗時,使用 HTTP 狀態碼與 OAuth error 欄位返回:
{
"error": "INVALID_CLIENT",
"error_description": "invalid client credentials"
}
| HTTP 狀態碼 | error 錯誤碼 | 含義與排查建議 |
|---|---|---|
| 400 | INVALID_REQUEST | 請求格式不是合法 JSON、grant_type 不為 client_credentials,或缺少必填欄位 |
| 401 | INVALID_CLIENT | 應用不存在、已停用/刪除,或 client_id 與 client_secret 不匹配 |
| 500 | SERVER_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;
}