使用OAuth 2.0仅应用认证调用X API发帖时出现权限错误
问题分析与解决:X平台发布推文认证失败
问题描述
用户编写了以下PHP+cURL代码尝试发布推文:
$api_key='xx'; $api_secret='yy'; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, 'https://api.twitter.com/oauth2/token'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Content-Type: application/x-www-form-urlencoded', ]); curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); curl_setopt($ch, CURLOPT_USERPWD, $api_key.':'.$api_secret); curl_setopt($ch, CURLOPT_POSTFIELDS, 'grant_type=client_credentials'); $response = curl_exec($ch); curl_close($ch); $response=json_decode($response); $access_token=$response->access_token; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, 'https://api.twitter.com/2/tweets'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Authorization: Bearer '.$access_token, 'Content-Type: application/json', ]); curl_setopt($ch, CURLOPT_POSTFIELDS, '{"text":"Hello, world!"}'); $response = curl_exec($ch); curl_close($ch); print_r($response);
成功获取access_token后,收到错误提示:
"Authenticating with OAuth 2.0 Application-Only is forbidden for this endpoint. Supported authentication types are [OAuth 1.0a User Context, OAuth 2.0 User Context]"
错误原因
你使用的是OAuth 2.0应用级认证(Application-Only),这种认证仅适用于无需绑定具体用户的操作(比如搜索公开推文、查看用户公开信息),但发布推文属于必须关联具体用户账号的操作,必须使用带用户上下文的认证方式:
- OAuth 1.0a 用户上下文
- OAuth 2.0 用户上下文(需通过用户授权流程获取的Access Token,而非应用自身凭证生成的token)
解决方案
方式1:使用OAuth 1.0a用户上下文认证
需提前通过用户授权流程获取用户的access_token和access_token_secret,代码示例如下:
$api_key = 'xx'; $api_secret = 'yy'; $user_access_token = '用户授权的access_token'; $user_access_token_secret = '用户授权的access_token_secret'; $url = 'https://api.twitter.com/2/tweets'; $method = 'POST'; $post_data = json_encode(['text' => 'Hello, world!']); // 构建OAuth参数 $oauth_params = [ 'oauth_consumer_key' => $api_key, 'oauth_nonce' => md5(uniqid(rand(), true)), 'oauth_signature_method' => 'HMAC-SHA1', 'oauth_timestamp' => time(), 'oauth_token' => $user_access_token, 'oauth_version' => '1.0' ]; // 生成签名 $base_string = $method . '&' . rawurlencode($url) . '&' . rawurlencode(http_build_query($oauth_params)); $signing_key = rawurlencode($api_secret) . '&' . rawurlencode($user_access_token_secret); $oauth_params['oauth_signature'] = base64_encode(hash_hmac('sha1', $base_string, $signing_key, true)); // 构建Authorization头 $auth_header = 'OAuth '; foreach ($oauth_params as $key => $value) { $auth_header .= rawurlencode($key) . '="' . rawurlencode($value) . '", '; } $auth_header = rtrim($auth_header, ', '); // 发送请求 $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_HTTPHEADER, [ $auth_header, 'Content-Type: application/json' ]); curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data); $response = curl_exec($ch); curl_close($ch); print_r($response);
方式2:使用OAuth 2.0用户上下文认证
需先通过OAuth授权码流程获取带tweet.write权限的用户级access_token,然后直接调用API:
$user_access_token = '用户授权的带write权限的OAuth2 access_token'; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, 'https://api.twitter.com/2/tweets'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Authorization: Bearer ' . $user_access_token, 'Content-Type: application/json' ]); curl_setopt($ch, CURLOPT_POSTFIELDS, '{"text":"Hello, world!"}'); $response = curl_exec($ch); curl_close($ch); print_r($response);
注意事项
- 用户授权流程需在X开发者平台配置回调地址,引导用户完成授权后获取对应token
- 确保应用已在X开发者平台申请并开启
tweet.write权限
内容的提问来源于stack exchange,提问作者vespino
相关产品推荐
相关产品推荐

