简体   繁体   English

带有服务帐户的Google OAuth2 - 指定要代表的用户电子邮件

[英]Google OAuth2 with Service Account - specifying the user email to act on behalf of

I'm trying to add events and reminders programmatically on my Google Calendar. 我正在尝试以编程方式在Google日历上添加活动和提醒。 I am using a Service Account . 我正在使用服务帐户

I can successfully add events to my Google Calendar but not the reminders. 我可以成功地将事件添加到我的Google日历,但不能添加提醒。 This is because the events are added by the Service Account Email (something like xyz@developer.gserviceaccount.com), and I should add reminders using my Gmail account, not the Service Account). 这是因为事件是由服务帐户电子邮件(类似于xyz@developer.gserviceaccount.com)添加的,我应该使用我的Gmail帐户而不是服务帐户添加提醒。

Fortunately, it is possible to act on behalf of my Gmail Account. 幸运的是,可以代表我的Gmail帐户执行操作。 See bottom of this page: https://developers.google.com/api-client-library/php/guide/aaa_oauth2_service#using 请参阅本页底部: https//developers.google.com/api-client-library/php/guide/aaa_oauth2_service#using
It suggests to add $cred->sub = "emailaddress@yourdomain.com"; 它建议添加$cred->sub = "emailaddress@yourdomain.com";

But I get the following error when adding this code: 但是在添加此代码时出现以下错误:

Google_Auth_Exception: Error refreshing the OAuth2 token, message: '{ "error" : "internal_failure" }' Google_Auth_Exception:刷新OAuth2令牌时出错,消息:'{“error”:“internal_failure”}'

I'm doing something wrong but I don't know what, here is my code below: 我做错了但我不知道是什么,这是我的代码如下:

$applicationName = 'applicationName';
$serviceAccountEmail = 'xyzg@developer.gserviceaccount.com';
$serviceAccountKeyPath = __DIR__ . '/xyz-privatekey.p12';
$serviceAccountClientId = 'xyz.apps.googleusercontent.com';

$client = new \Google_Client();
$client->setApplicationName($applicationName);
$service = new \Google_Service_Calendar($client);

if (isset($_SESSION['service_token'])) {
    $client->setAccessToken($_SESSION['service_token']);
}
$key = file_get_contents($serviceAccountKeyPath);
$cred = new \Google_Auth_AssertionCredentials(
    // $serviceAccountName
    $serviceAccountEmail,
    // $scopes array List of scopes
    array('https://www.googleapis.com/auth/calendar'),
    // $privateKey
    $key
);
$client->setClientId($serviceAccountClientId);
$cred->sub = 'myEmail@gmail.com';
$client->setAssertionCredentials($cred);
if ($client->getAuth()->isAccessTokenExpired()) {
    $client->getAuth()->refreshTokenWithAssertion(); // fails on this line
}
$_SESSION['service_token'] = $client->getAccessToken();

PS: If I uncomment $cred->sub = 'myEmail@gmail.com'; PS:如果我取消注释$cred->sub = 'myEmail@gmail.com'; the code doesn't throw an exception 代码不会抛出异常

Service account impersonating the user only applies to Google Apps, see https://code.google.com/p/google-apps-manager/wiki/GAM3OAuthServiceAccountSetup 模拟用户的服务帐户仅适用于Google Apps,请参阅https://code.google.com/p/google-apps-manager/wiki/GAM3OAuthServiceAccountSetup

If you want your app to access any user's Calendar, you should use the standard OAuth2 flow to get the consent of the user and store the refresh token for future use (since you're trying to use service account I assume this is a server side app). 如果您希望您的应用访问任何用户的日历,您应该使用标准OAuth2流程获得用户的同意并存储刷新令牌以供将来使用(因为您尝试使用服务帐户我认为这是服务器端应用程序)。 If the only user is yourself and you don't plan to distribute you app to anyone else, you could hardcode the refresh token in your server. 如果唯一的用户是您自己并且您不打算将应用程序分发给其他任何人,则可以在服务器中对刷新令牌进行硬编码。 Here is the documentation for Google OAuth2 web server flow: https://developers.google.com/accounts/docs/OAuth2WebServer 以下是Google OAuth2网络服务器流程的文档: https//developers.google.com/accounts/docs/OAuth2WebServer

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM