跳到主要内容

获取 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;
}