问题描述
我有 3 个使用驱动 sdk 的服务帐户.
I have 3 service accounts that are using the drive sdk.
1 有效,2 无效.
返回的错误是Error refresh the OAuth2 token, message: '{ "error" : "unauthorized_client", "error_description" : "Unauthorized client or scope in request." }'"
The error that comes back is "Error refreshing the OAuth2 token, message: '{ "error" : "unauthorized_client", "error_description" : "Unauthorized client or scope in request." }'"
所有 3 个帐户均已在开发者控制台中注册.所有这 3 个都被授权在 Google Apps 控制台中进行托管客户端 API 访问".所有 3 都具有范围https://www.googleapis.com/auth/drive.readonly一个>".驱动器中的所有 3 个,都有一个特定的文件夹供仅查看"共享.
All 3 accounts are registered in the developer console. All 3 are authorised for "Managed Client API access" within Google Apps Console. All 3 have the scope "https://www.googleapis.com/auth/drive.readonly". All 3 in drive, has a specific folder for it shared for "view only".
我正在使用 PHP,我向页面传递了一个参数,该参数称为类型",它反映了帐户的用途,1 用于公共,1 用于会员,1 用于管理员.
I am using PHP and I pass one parameter to the page which is called "type" and reflects what the purpose of the account is for, 1 for public, 1 for member and 1 for admin.
例如
http://www.somehost.com/oauth_client.php?type=googledrive_admin
p12 证书和用户值存储在服务器上.所有ini"文件都具有相同的值结构、client_id、client_email、范围和查询过滤器.在所有情况下,文件之间唯一更改的项目是 client_id 和 client_email.
The p12 certificate and user values are stored on the server. All "ini" files have the same structure of values, client_id, client_email, scope and query filter. In all cases the only item that changes between the files is the client_id and client_email.
我的代码如下:
<?php
include (__DIR__ . "/google-api-php-client/autoload.php");
google_api_php_client_autoload("Google_Auth_AssertionCredentials");
google_api_php_client_autoload("Google_Client");
google_api_php_client_autoload("Google_Service_Drive");
google_api_php_client_autoload("Google_Service_OAuth2");
$type = $_GET['type'];
$path = __DIR__ . "/secure/";
$certificate = $path . $type . ".p12";
$ini_path = $path . $type . ".ini";
$ini = parse_ini_file($ini_path);
$service_scope = $ini['scope'];
$service_account_id = $ini['id'];
$service_account_email = $ini['email'];
$service_query = $ini['q'];
$service_account_key = file_get_contents($certificate);
$credentials = new Google_Auth_AssertionCredentials(
$service_account_email,
array($service_scope),
$service_account_key
);
$credentials -> sub = $service_account_email;
$google_client = new Google_Client();
$google_client -> setAssertionCredentials($credentials);
if ($google_client -> getAuth() -> isAccessTokenExpired()) {
$google_client -> getAuth() -> refreshTokenWithAssertion(); **//FAILS HERE**
}
$drive = new Google_Service_Drive($google_client);
$result = array();
$pageToken = NULL;
do {
try {
$parameters = array();
if ($pageToken) {
$parameters['pageToken'] = $pageToken;
}
$parameters['q'] = $service_query;
$files = $drive -> files -> listFiles($parameters);
$result = array_merge($result, $files -> getItems());
$pageToken = $files -> getNextPageToken();
} catch (Exception $e) {
print "An error occurred: " . $e -> getMessage();
$pageToken = NULL;
}
} while ($pageToken);
echo json_encode($result) . "
";
?>
每个ini文件的结构如下
Each ini file is structured as follows
id="35{code}.apps.googleusercontent.com"
email="35{code}@developer.gserviceaccount.com"
scope="https://www.googleapis.com/auth/drive.readonly"
q="mimeType != 'application/vnd.google-apps.folder'"
我无法弄清楚为什么当我对所有服务帐户都进行了相同的过程时,这对一个服务帐户而不是其他服务帐户有效.任何想法和帮助表示赞赏.
What I just cannot work out is why this works for one service account and not the others when I have gone through the same process for all of them. Any ideas and help appreciated.
推荐答案
感谢您的这篇文章以及您对Resolved by remove the line $credentials -> sub = $service_account_email;
"
Thanks for this post and your comment about "Resolved by removing the line $credentials -> sub = $service_account_email;
"
我面临着类似的问题 这里.显然, $credentials ->sub = $service_account_email
仅适用于在 Google Developers Console 中创建的第一个/主要服务帐户.除此之外,它还会在某些 OAuth2 范围内产生意外错误(就像我在 Fusion Tables 中遇到的那样).
I am facing a similar issue here. Apparently, $credentials -> sub = $service_account_email
is only accepted for the first/primary service account created in the Google Developers Console. Besides that, it will also produce unexpected errors with certain OAuth2 scopes (as what I encountered with Fusion Tables).
因此,这里是一般建议:
Hence, here is the general advise:
不要包含 $credentials ->sub = $service_account_email
不必要.
仅当您尝试冒充差异用户(条件是适当的设置具有已在 Google Apps 管理控制台中正确完成).
尽管在某些情况下它可能不会产生任何错误,但在将服务帐户本身的电子邮件地址包含在 JWT 声明集中作为sub"字段的值时,会出现一些意外行为.
这篇关于谷歌驱动服务帐户和“请求中的未经授权的客户端或范围"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!