Repository navigation
Client is unauthorized to retrieve access tokens using this method" w/ Service Account #2214
Description
PROBLEM / CAUSE: I am using google-php-api-client to create calendar event, with service account and set the subject, subject email address is my admin account, with out subject this is working but when i am set subject this is not working and given error Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested,
When i am calling throw google API this is working properly
API Calling code is :
define('CALENDAR_ID', <claendar_id>);
/*********************** Start: Create access Token***********************************/
function base64url_encode($data) {
return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}
function getJwtAssertion($private_key_file)
{
$json_file = file_get_contents($private_key_file);
$info = json_decode($json_file);
$private_key = $info->{'private_key'};
//{Base64url encoded JSON header}
$jwtHeader = base64url_encode(json_encode(array(
"alg" => "RS256",
"typ" => "JWT"
)));
//{Base64url encoded JSON claim set}
$now = time();
$jwtClaim = base64url_encode(json_encode(array(
"iss" => <serviceaccount>,
"sub" => <admin_email_address>,
"scope" => "https://www.googleapis.com/auth/calendar",
"aud" => "https://www.googleapis.com/oauth2/v4/token",
"exp" => $now + 3600,
"iat" => $now
)));
$data = $jwtHeader.".".$jwtClaim;
// Signature
$Sig = '';
openssl_sign($data,$Sig,$private_key,'SHA256');
$jwtSign = base64url_encode($Sig);
$jwtAssertion = $data.".".$jwtSign;
return $jwtAssertion;
}
function getGoogleAccessToken($private_key_file)
{
$result = [
'success' => false,
'message' => '',
'token' => null
];
if(!file_exists($private_key_file)){
$result['message'] = 'Google json key file missing!';
return $result;
}
$jwtAssertion = getJwtAssertion($private_key_file);
try {
$payload = [
'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer',
'assertion' => $jwtAssertion
];
$url = 'https://oauth2.googleapis.com/token';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
$data = json_decode(curl_exec($ch), true);
$http_code = curl_getinfo($ch,CURLINFO_HTTP_CODE);
if($http_code != 200){
$result['message'] = 'Error : Failed to access token';
} else {
$result['token'] = $data['access_token'];
$result['success'] = true;
}
} catch (RequestException $e) {
$result['message'] = $e->getMessage();
}
return $result;
}
$KEY_FILE_LOCATION = __DIR__.'/key_file.json';
$googleToken = getGoogleAccessToken($KEY_FILE_LOCATION);
/*********************** End Create access Token***********************************/
if(isset($googleToken['token'])){
$access_token = $googleToken['token'];
getCalendarDetails($access_token);
}
function getCalendarDetails($access_token) {
$url_events = 'https://www.googleapis.com/calendar/v3/calendars/claendar_id';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url_events);
// curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Authorization: Bearer '. $access_token, 'Content-Type: application/json'));
$data = curl_exec($ch);
$http_code = curl_getinfo($ch,CURLINFO_HTTP_CODE);
echo "<pre>";
print_r($data);
die();
}
But i am set the subject with Google php client is not working
My code is :
require_once 'vendor/autoload.php';
putenv('GOOGLE_APPLICATION_CREDENTIALS='.__DIR__.'/clanedar_key.json');
$calendarId = <calendar_id>;
$client = new Google_Client();
// use the application default credentials
$client->useApplicationDefaultCredentials();
$client->setSubject("admin_gmail_account");
$client->addScope([Google_Service_Calendar::CALENDAR_EVENTS, Google_Service_Calendar::CALENDAR]);
$service = new Google_Service_Calendar($client);
$optParams = array(
'maxResults' => 10,
'orderBy' => 'startTime',
'singleEvents' => true,
'timeMin' => date('c', strtotime('2022-01-28 9:00am -1 minute')),
'timeMax' => date('c', strtotime('2022-02-28 10:00am +1 minute')),
);
$results = $service->events->listEvents($calendarId, $optParams);
foreach ($results->getItems() as $event) {
$start = $event->start->dateTime;
$start = !$start ? $event->start->date : $start;
$end = $event->end->dateTime;
printf($event->getSummary() . "<br>" . $start . "<br>" .$end. "<br>". $event->hangoutLink ."<br><br>");
}
Seen Error :
Fatal error: Uncaught Google\Service\Exception: { "error": "unauthorized_client", "error_description": "Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested." } in /var/www/html/google-api-php-client-main/src/Http/REST.php:128 Stack trace: #0 /var/www/html/google-api-php-client-main/src/Http/REST.php(103): Google\Http\REST::decodeHttpResponse() googleapis/google-api-dotnet-client#1 [internal function]: Google\Http\REST::doExecute() googleapis/google-api-dotnet-client#2 /var/www/html/google-api-php-client-main/src/Task/Runner.php(182): call_user_func_array() googleapis/google-api-dotnet-client#3 /var/www/html/google-api-php-client-main/src/Http/REST.php(66): Google\Task\Runner->run() googleapis/google-api-dotnet-client#4 /var/www/html/google-api-php-client-main/src/Client.php(918): Google\Http\REST::execute() googleapis/google-api-dotnet-client#5 /var/www/html/google-api-php-client-main/src/Service/Resource.php(238): Google\Client->execute() googleapis/google-api-dotnet-client#6 /var/www/html/google-api-php-client-main/vendor/google/apiclient-services/src/Calendar/Resource/Events.php(271): Google\Service\Resource->call() googleapis/google-api-dotnet-client#7 /var/www/html/google-api-php-c in /var/www/html/google-api-php-client-main/src/Http/REST.php on line 128
Activity
amanda-tarafa commentedon Feb 14, 2022
I am moving this issue to the PHP repo as this is the .NET repo.
LindaLawton commentedon Apr 25, 2022
There are serval types of clients that you can create on google cloud console. Service account , web, native and some mobile ones. The code used to authorize them is different. You cant use web credentials with code designed for use with a service account. I would check that you actually have service account credentials.
paseto commentedon Mar 1, 2023
Any updates on this?
Really makes no sense, I use cloud console(with normal Gmail user) and create a service account.
Then I cannot use this service account without have a Workspace Admin User Account to use the API.
LindaLawton commentedon Mar 2, 2023
@paseto service accounts don't work with standard Gmail user accounts for either the google calendar api or the gmail api. You need to have a google workspace domain account and configure domain wide delegation to a user on the domain.
There's no update for that its working as intended.
paseto commentedon Mar 2, 2023
Thanks @LindaLawton, I'll try oauth2 with refresh token since I only need to access a calendar from a single gmail user account.
LindaLawton commentedon Mar 5, 2023
Just remember to set your app to production when your ready. Apps in testing have their refresh tokens expired after seven days.
UVLabs commentedon Jan 21, 2024
This one comment saved me so much time after hours trying to debug why the heck I couldn't get this to work.
I watched a tutorial and in it a service account was created and it worked with the service account. I even downloaded the zip that the video creator uploaded and tested it and it worked. But when I tried my code the same way...it didn't.
I assume this is due to some changes in the Google API client library where the latest ones do not allow service accounts to access and edit calendars without "domain wide delegation" which you need a google workspace account to get!
I resorted to using OAuth and it worked just fine.
@paseto Are you aware of the rate limits for test accounts added to an OAuth app? The ones added here:
I tried finding a definite answer but couldn't find any. I would be the only one using the app to create calendar events in my own calendar, so don't need any crazy limit but would still like to know...probably about 100 scheduled calendar events a day
codev-agency commentedon Mar 21, 2024
@amanets did you could fixed it? I have same error
mohsin889 commentedon Apr 17, 2024
I have a service account with domain wide deligation enabled and when i impersonate the user and add an attendee to the event it gives me the error
{ "error": "unauthorized_client", "error_description": "Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested."}Code that I'm using to create an event and add attendee.
ahming9486 commentedon May 27, 2025
Same issue here, any updates for this?
monkeyArms commentedon Aug 21, 2025
@UVLabs - I wound up here from a google search due to similar issues. Thank you for the incredibly helpful comment and code sample - I'm rolling now!