通过 OAuth 对 Google API 进行经过身份验证的调用时遇到问题

Posted

技术标签:

【中文标题】通过 OAuth 对 Google API 进行经过身份验证的调用时遇到问题【英文标题】:Trouble making authenticated calls to Google API via OAuth 【发布时间】:2014-05-11 10:48:25 【问题描述】:

当我尝试使用服务器到服务器身份验证调用 Google Directory API 时,我收到错误消息“未授权访问此资源/api”。

我做了什么:

    在 Google Developers Console 中创建了一个应用。 已下载私钥并查找服务帐户名称。 在 API 下激活了 Admin SDK。 已下载 google-api-php-client。 写了如下代码:

$serviceAccountName = 'XXXXXXXXXXX@developer.gserviceaccount.com';
$scopes = 'https://www.googleapis.com/auth/admin.directory.group';
$privateKeyFile = dirname(__FILE__).'/../certs/googleapi-privatekey.p12';

$client = new Google_Client();
$client->setApplicationName('API Project');
$client->setScopes($scopes);
$cred = new Google_Auth_AssertionCredentials($serviceAccountName, $scopes, file_get_contents($privateKeyFile));
$client->setAssertionCredentials($cred);
$client->getAuth()->refreshTokenWithAssertion();

$req = new Google_Http_Request("https://www.googleapis.com/admin/directory/v1/groups/group-id@example.com/members?maxResults=1000");

$val = $client->getAuth()->authenticatedRequest($req);

var_dump($client->getAuth()->getAccessToken());
var_dump($val->getResponseBody());
    执行该小脚本会产生一个有效的访问令牌,有效期为一小时,并显示以下错误消息:

"error": "errors": [ "domain": "global", "reason": "forbidden", "message": "未授权访问此资源/api" ], "code ": 403, "message": "未授权访问此资源/api"

当我尝试使用我的 PHP 脚本中的访问密钥在 Google OAuth 操场上执行相同的请求时,我得到了同样的错误。我是否必须在 Developers Console 中的某处激活对该服务帐户的组数据的访问权限?

【问题讨论】:

你试过了吗? developers.google.com/admin-sdk/directory/v1/guides/delegation 没有。但我现在这样做了;-)。我仍然收到错误消息。但是您发布的文章中有一个提示:“只有有权访问 Admin API 的用户才能访问 Admin SDK Directory API,因此您的服务帐户需要模拟其中一个用户才能访问 Admin SDK Directory API。”如何为服务帐户启用对 Admin SDK 的访问?!到目前为止,我只是在整个项目的 APIs 下激活了 Admin SDK。 该页面上的“将域范围的权限委派给您的服务帐户”部分不是这样描述的吗? 不完全是。我可以将域范围的访问权限委派给那里的给定范围。但不是 API。 developers.google.com/admin-sdk/directory/v1/guides/delegation 下的文档在“将域范围的权限委托给您的服务帐户”部分底部的注释中特别指出,此外还需要访问 API:“只有有权访问 Admin API 的用户才能访问Admin SDK Directory API,因此您的服务帐户需要模拟其中一位用户才能访问 Admin SDK Directory API。”。 【参考方案1】:

除了授予服务帐户客户端 ID 访问您的 Google Apps 控制面板中给定范围的权限外,您还需要告诉服务帐户在您的 Google Apps 域中模拟超级管理员用户:

$auth->sub = $adminEmail;

由于某种原因,Admin SDK 文档不包含 PHP 示例,但在 Google Drive 文档中有instantiating a service account 的示例代码。

【讨论】:

非常感谢!那完全奏效了!是的,遗憾的是文档和错误消息不是很有帮助。我使用了上面的代码,只添加了一行: $cred = new Google_Auth_AssertionCredentials($serviceAccountName, $scopes, file_get_contents($privateKeyFile)); $cred->sub = 'XXXX@my-domain.com'; $client->setAssertionCredentials($cred);【参考方案2】:

我通过反复试验发现 删除了“管理员”。从范围使其工作(除了上面所说的关于遵循这些步骤的所有内容:https://developers.google.com/drive/web/delegation#delegate_domain-wide_authority_to_your_service_account)。

$cs = json_decode(file_get_contents(<MY SECRET PATH> . 'client_secrets.json'), true); 
$cs = $cs['web'];
$cred = new Google_Auth_AssertionCredentials(
    $cs['client_email'], //why do they call this "service account name" ? Misleading >:(
    array(
        'https://www.googleapis.com/auth/directory.user',
        'https://www.googleapis.com/auth/directory.group',
        'https://www.googleapis.com/auth/directory.group.member'
    ),
    $key,
    'notasecret',
    'http://oauth.net/grant_type/jwt/1.0/bearer',
    '<MY EMAIL IN THE DOMAIN>' //_my_ email as an user with admin rights
);

【讨论】:

以上是关于通过 OAuth 对 Google API 进行经过身份验证的调用时遇到问题的主要内容,如果未能解决你的问题,请参考以下文章

通过 OAuth 2.0 自动使用 google-api-dotnet-client

使用第 3 方 Oauth 提供程序对 API 用户进行身份验证 [关闭]

通过 OAuth 2.0 和私钥(即服务帐户)访问 Google Contacts Api

Google 通过 OAuth2 身份验证从 JavaScript 客户端联系 API 问题

授权命令行工具使用 Google API(通过 OAuth2.0 或其他任何方式)

关闭Google+后,OAuth API也会消失吗?