获取访问令牌时服务帐户 API 错误
Posted
技术标签:
【中文标题】获取访问令牌时服务帐户 API 错误【英文标题】:Service account API error when getting the access token 【发布时间】:2021-12-02 22:15:11 【问题描述】:我正在为我们的网络应用程序测试 google people API。 步骤:
我在 google 控制台 (https://console.cloud.google.com/) 中创建了新项目 我启用了 People API 我为我的应用程序和 API 密钥创建了所需的凭据 - Web 客户端 我使用 p12 密钥为服务器到服务器查询创建了服务帐户,并启用了“Google Workspace 域范围委派” 我配置了 OAuth 同意屏幕,其中包含授权给 google 和访问人员 API 所需的范围:/auth/userinfo.email /auth/userinfo.profile /auth/contacts /auth/contacts.readonly 然后我的 php 脚本使用“Google API PHP 客户端”创建重定向链接到同意屏幕,并使用 Web 客户端返回访问令牌代码:<?php
$client = new Google_Client();
$client->setAccessType('online'); // default: offline
$client->setApplicationName('My Project xxxxx');
$client->setClientId('999999999999-qwertysdfhwe9uriiiiiiiiiiiiiiiii.apps.googleusercontent.com');
$client->setClientSecret('GOCSPX-hhhhhhhhhhhhhhhhhhhhhhhhhhhh');
$client->setDeveloperKey('AIzafffffffffffffffffffffffffffffffffff'); // API key
$client->setState('subdomain.myapp.com');
$scriptUri = 'https://oauth.myapp.com/auth.php';
$client->setRedirectUri($scriptUri);
$client->addScope('https://www.googleapis.com/auth/userinfo.email');
$client->addScope('https://www.googleapis.com/auth/userinfo.profile');
$client->addScope('https://www.googleapis.com/auth/contacts');
$auth_url = $client->createAuthUrl();
header('Location: '.$auth_url);
?>
此代码重定向到 google 身份验证屏幕,然后我使用 google 登录并批准范围。谷歌将我重定向回我的应用程序,现在我有了访问令牌和经过验证的用户的批准范围和电子邮件。
下一步我遇到了很大的麻烦 - 服务器到服务器查询以获取人员 API 的访问令牌
function base64_url_encode($input)
return str_replace('=', '', strtr(base64_encode($input), '+/', '-_'));
$iat = time();
$url = "https://www.googleapis.com/oauth2/v4/token";
$scope = 'https://www.googleapis.com/auth/contacts';
$jwt_data = array(
'iss' => '111111111111111111111', // My service account ID
'aud' => $url,
'scope' => $scope,
'exp' => $iat + 3600,
'iat' => $iat,
'sub' => 'user@gmail.com', // Email of the user that was autenticated in first step
);
openssl_pkcs12_read(file_get_contents('keyfile.p12'), $certs, 'notasecret');
$header = array('typ' => 'JWT', 'alg' => 'RS256');
$signing_input = base64_url_encode(json_encode($header)) . '.' . base64_url_encode(json_encode($jwt_data));
openssl_sign($signing_input, $signature, $certs['pkey'], 'SHA256');
$jwt = $signing_input . '.' . base64_url_encode($signature);
$data = array(
"grant_type" => "urn:ietf:params:oauth:grant-type:jwt-bearer",
"assertion" => $jwt
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
$response = curl_exec($ch);
curl_close($ch);
$google_contacts_api_tokens_collection[$use_mailbox] = $response;
return $response;
而这段代码google返回了我无法修复的错误,我没有任何想法。
错误文本: “客户端未授权使用此方法检索访问令牌,或者客户端未授权任何请求的范围。”
【问题讨论】:
用户是 Google Accounts 用户 (Gmail) 还是 Google Workspace 用户?你只能冒充第二种用户。 【参考方案1】:您的代码正试图通过服务帐户模拟用户。这需要启用域范围委派。反过来,错误消息意味着服务帐户没有权限,因为未启用委派。
Perform Google Workspace Domain-Wide Delegation of Authority
如果用户不是 Google Workspace 的一部分,则您不能冒充该用户。
【讨论】:
【参考方案2】:是的,但我已经尝试过了,但没有帮助。我在 Google Workspace 中为服务帐户配置了范围,并在 Google 控制台中选中了“启用 Google Workspace 域范围委派”复选框。在 Google Workspace 中,我使用了我的服务帐号的数字客户端 ID。
我还发现了一个奇怪的时刻:
Web 客户端总是返回良好的访问令牌,但是当我请求服务帐户访问令牌时,它仅适用于谷歌控制台项目所有者 ('sub' => 'project.owner@gmail.com')。如果我为另一个用户请求服务帐户访问令牌 ('sub' => 'project.testuser@gmail.com'),Google 也会返回相同的错误:Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested.
【讨论】:
以上是关于获取访问令牌时服务帐户 API 错误的主要内容,如果未能解决你的问题,请参考以下文章
当我尝试验证测试购买产品时 - 出现错误 410?购买.产品获取
BigtableConnection API 失败;从元数据服务器获取访问令牌时出错