简体   繁体   中英

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. I am using a Service Account .

I can successfully add events to my Google Calendar but not the reminders. 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).

Fortunately, it is possible to act on behalf of my Gmail Account. See bottom of this page: https://developers.google.com/api-client-library/php/guide/aaa_oauth2_service#using
It suggests to add $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" }'

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'; 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

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). 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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