I understand that there were already similar questions here, but the answers to them did not help me.
Trying to connect through a service account to the calendars of users who are part of the domain. For connection I use Google API PHP Client (https://github.com/googleapis/google-api-php-client)
Account setup followed the instructions (https://developers/admin-sdk/directory/v1/guides/delegation)
Here's my code:
<?php
require '/vendor/autoload.php';
$client = new Google_Client();
putenv('GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json');
$client->useApplicationDefaultCredentials();
$client->authorize();
$scopes = implode(' ', [Google_Service_Calendar::CALENDAR, Google_Service_Calendar::CALENDAR_EVENTS]);
$client->setScopes($scopes);
$client->setSubject('user#email.com');
$service = new Google_Service_Calendar($client);
$optParams = [
'maxResults' => 10,
'orderBy' => 'startTime',
'singleEvents' => TRUE,
'timeMin' => date('c')
];
$results = $service->events->listEvents('root#email.com', $optParams);
$events = $results->getItems();
And then I get an authorization error:
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."
}
Can you tell me if someone 's already faced a mistake like this? Should the root#email.com be mail or mail that was generated during access setup? Or is the problem somewhere else at all?
Thank you in advance for any help!
Your code is actually correct. Be sure you authorized your service account to use the same scopes you are trying to use in your code. This is a common issue with service accounts.
Here a walk-through from the docs:
Go to your G Suite domain’s Admin console.
Select Security from the list of controls. If you don't see Security listed, select More controls from the gray bar at the bottom of the page, then select Security from the list of controls.
Select Advanced settings from the list of options.
Select Manage API client access in the Authentication section.
In the Client name field, enter the client ID obtained from the service account creation steps above.
In the One or More API Scopes field enter the scopes required for your application (for a list of possible scopes, see Authorize requests).
For example, if you require domain-wide access to Calendar and Calendar Events: https://www.googleapis.com/auth/calendar, https://www.googleapis.com/auth/calendar.events
Click the Authorize button.
Related
I am trying to use service account with domain delegation so I can automate some tasks of google classroom via cron. For this I need service account with domain delegation.
I am working and struggling in it for 3 days. I have properly read documentation so many times. You can imagine the 3 days research. Now I am getting exhaust and finally come here in the hope.
I am using php library provided by google for google classroom.
https://github.com/googleapis/google-api-php-client
I am getting this error
Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested.
Which means in google documentation enter image description here
I tried that several times but still getting this errror.
Here is my php code
require_once plugin_dir_path(__FILE__).'../../xf-google-classroom/vendor/autoload.php';
$this->scopes = [
Google_Service_Classroom::CLASSROOM_COURSES,
//Google_Service_Classroom::CLASSROOM_ROSTERS,
//Google_Service_Classroom::CLASSROOM_COURSES_READONLY,
//Google_Service_Classroom::CLASSROOM_COURSEWORK_ME,
//Google_Service_Classroom::CLASSROOM_COURSEWORK_ME_READONLY,
//Google_Service_Classroom::CLASSROOM_COURSEWORK_STUDENTS,
Google_Service_Classroom::CLASSROOM_COURSEWORK_STUDENTS_READONLY,
//Google_Service_Classroom::CLASSROOM_PROFILE_EMAILS,
];
$this->credentials = plugin_dir_path(__FILE__) . '/sufi-new-2.json';
//$this->redirect_uri = site_url( 'wp-admin/admin.php?page=bp-groups' );
$this->client = new Google_Client();
//$this->client->useApplicationDefaultCredentials();
$jsonKey = [
"type"=> "service_account",
"project_id"=> "edufix-upgraded",
"client_email"=> "newsufyan#edufix-upgraded.iam.gserviceaccount.com",
"client_id"=> "115746479435703189142",
"auth_uri"=> "https://accounts.google.com/o/oauth2/auth",
"token_uri"=> "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url"=> "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url"=> "https://www.googleapis.com/robot/v1/metadata/x509/newsufyan%40edufix-upgraded.iam.gserviceaccount.com"
];
$this->client->setAuthConfig( $jsonKey );
$this->client->setSubject('clases#krugerschool.edu.ec');
//$this->client->setRedirectUri( $this->redirect_uri );
$this->client->addScope( $this->scopes );
$this->client->setAccessType( 'offline' );
Let me tell you that my OAuth2 authentication with conscent screen application is working good on frontend for users. I am not able to run my cron scripts because of this domain delegation.
Also my OAuth Consent screen is in test mode and I have added test users in it. And working good with users on frontend with consent screen.
Also I always generate new key after any new changes and deploy that new credentials as well everytime. I tried to remove and add again with client id and proper scopes and domain delegation again and again but not working.
Also I have added that my administrator account in service account and grant access to owner. But not not worked.
Kindly help
I am trying to solve my problem and expecting a poper solution
I can't get the Locations list from my business under my code (PHP using the "Google APIs Client Library for PHP" together with "Google_Service_MyBusiness" Classes) when I use the "Service Account" authentication, the API returns an empty Location List.
I already have the Prerequisites and did the Basic setup, by the way, I got the information with success on OAuth Playground, under a specific AccountId, Eg: 1111111111, provided by another response there on the "OAuth Playground".
(PS: I tested with my "PERSONAL" and "LOCATION_GROUP" accounts and got success with both).
But when I try to do it over my code via Server Account authentication, I can't get all the information, just the Account data that return another AccoundId, Eg: 2222222222, different of the Accounts that I got on OAuth Playground.
I did the Authentication process on OAuth Playground, using the same project where I created the "Service Account", by the way, the Permission of this "Service Account" is OWNER.
Previously, my role in my company on the Google My Business was "SITE_MANAGER", so I saw a forum answer where just "MANAGER" level/role can list the Locations, so I requested to change my permission, but continues as not the success on Locations listing.
So, I saw another Google My Business support article recommending create a "Location Group" and put my current "Location" into this group to make easy handle it, I did it and no success again.
My code is simple, based on Google guide, OAuth 2.0 for Server to Server Applications, and some Forum Questions (BTW the author's question have the same issue than me):
<?php
putenv('GOOGLE_APPLICATION_CREDENTIALS=service-account-credentials.json');
$client = new Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope("https://www.googleapis.com/auth/plus.business.manage");
require_once('Google_Service_MyBusiness.php');
$mybusinessService = new Google_Service_MyBusiness($client);
$accounts = $mybusinessService->accounts;
$accountsList = $accounts->listAccounts()->getAccounts();
foreach ($accountsList as $accKey => $account) {
var_dump('$account->name', $account->name);
$locations = $mybusinessService->accounts_locations;
$locationsList = $locations->listAccountsLocations($account->name)->getLocations();
var_dump('$locationsList', $locationsList);
// Final Goal of my Code
if (empty($locationsList)===false) {
foreach ($locationsList as $locKey => $location) {
$reviews = $mybusinessService->accounts_locations_reviews;
$listReviewsResponse = $reviews->listAccountsLocationsReviews($location->name);
$reviewsList = $listReviewsResponse->getReviews();
var_dump('$reviewsList', $reviewsList);
}
}
}
I expected the Location of my business (also the reviews, but it a next step), but I just got the empty Location list.
Finally, I got success using the ClientId/ClientSecret keys together with Refresh Token previously received on Google OAuth 2 Playground on the first time that I give permission to (my) App, instead "Service Account" authentication way :)
$client = new Google_Client();
$client->setClientId($clientId);
$client->setClientSecret($clientSecret);
$client->addScope("https://www.googleapis.com/auth/plus.business.manage");
$client->setSubject('my email user on GMB');
$client->refreshToken(' ###### ')
Now I got all the needed data for my application.
I'm trying to retrieve data from an AdSense account through the AdSense Management API.
I have successfully retrieved data using Google APIs Explorer when connected with my AdSense account.
I am now trying to get this data from a PHP script which will be run in a crontab.
My understanding is that I need a Service account which I created and I generated a json file.
The following code fails if I try to use the json file with two different errors :
if I use the setSubject with the owner of the AdSense account :
"error": "unauthorized_client",
"error_description": "Client is unauthorized to retrieve access tokens using this method."
If I comment the setSubject :
"reason": "noAdSenseAccount",
"message": "User does not have an AdSense account."
Code:
<?php
require_once '../../vendor/autoload.php';
putenv('GOOGLE_APPLICATION_CREDENTIALS=../conf/Mercury-testlpstats.json');
$client = new Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope('https://www.googleapis.com/auth/adsense.readonly');
//$client->setSubject('AdTech#Lagardere-Pub.com');
$service = new Google_Service_AdSense($client);
$startDate = '2017-05-01';
$endDate = '2017-05-01';
$optParams = array(
'metric' => array('INDIVIDUAL_AD_IMPRESSIONS', 'EARNINGS'),
'dimension' => 'DATE',
'filter' => array('AD_UNIT_ID==ca-pub-XXXX:YYYY'),
'useTimezoneReporting' => true
);
$report = $service->accounts_reports->generate('pub-ZZZZZ', $startDate, $endDate, $optParams);
2nd attempt with OAuth
I've created a OAuth account in https://console.cloud.google.com/apis/credentials/oauthclient/. When I check the AdSense API, my account appears in the list of authorized users in https://console.cloud.google.com/apis/api/adsense.googleapis.com/overview.
I've downloaded the corresponding JSON and changed my code but it still says:
"insufficientPermissions" if I set $client->useApplicationDefaultCredentials();
"Login Required" otherwise
require_once '../../vendor/autoload.php';
$client = new Google_Client();
$client->setAccessType('online');
$client->setAuthConfigFile('/home/al1/lpstats/conf/client_secret_725834039890-klbuc13f8089rjh7eis439b93n7sqqfv.apps.googleusercontent.com.json');
$client->addScope('https://www.googleapis.com/auth/adsense.readonly');
$service = new Google_Service_AdSense($client);
$startDate = '2017-05-01';
$endDate = '2017-05-01';
$optParams = array(
'metric' => array('INDIVIDUAL_AD_IMPRESSIONS', 'EARNINGS'),
'dimension' => 'DATE',
'filter' => array('AD_UNIT_ID==ca-pub-5035025648894332:3442683203'),
'useTimezoneReporting' => true
);
$report = $service->accounts_reports->generate('pub-5035025648894332', $startDate, $endDate, $optParams);
unauthorized_client
Means that the user you are authencating with does not have access to the Adsence Account you are trying to access.
Service account support
There are a number of Google APIs which don't support service accounts. Most noticeably would be YouTube API which does not even have a way of sharing your account with another user.
There are others which will allow you to share your data with another user but require that the user in question respond to an email notification. Blogger is one and Adsence is apparently another.
Solution
You will need to authenticate using Oauth2 using a user who has access to the adsence account in question. Authenticate your code once save the refresh token and use the refresh token to request a new access token within your cron job.
I am using Google APIs PHP client to to access the Google Drive API.
My problem is that I want to get permission to access user email. However the authenticate screen doesn't show the permission I am seeking. It just display "Application would like to ....Have offline access. But when done from the Google API playground, it correctly displays access to users email prompt.
So I think there is something wrong in my code level while creating authenticate url. Please help me to resolve the issue.
$client = new Google_Client();
$guzzleClient = new \GuzzleHttp\Client(array( 'curl' => array( CURLOPT_SSL_VERIFYPEER => false, ), ));
$client->setHttpClient($guzzleClient);
$client->setAuthConfig($oauth_credentials);
$client->setRedirectUri($redirect_uri);
$client->setAccessType('offline');
$client->setApprovalPrompt('force');
$client->setState($this->uri->segment(3));
$client->addScope("https://www.googleapis.com/auth/drive");
If all you want is the email address of the current authencated user you can simply go though the google drive api.
About.get method Gets information about the user, the user's Drive, and system capabilities.
{
"user": {
"kind": "drive#user",
"displayName": "Linda Lawton",
"photoLink": "xxxx",
"me": true,
"permissionId": "xxxx",
"emailAddress": "xxxx#gmail.com"
}
}
Side note on scope:
Scopes are what tells the user what data you want to access. https://www.googleapis.com/auth/drive basically says you want full access to their Google drive account https://www.googleapis.com/auth/classroom.profile.emails would request access to their email address.
Offline access
'offline' tells the user you want to be able to access their account when they are not using your application. By adding this you will receive a refresh token which you can save and use at anytime to get a new access token to access a users data.
I'm getting
Error calling GET https://www.googleapis.com/admin/directory/v1/users/email#example.com.com: (403) Not Authorized to access this resource/api
when running
$client = new Google_Client();
$client->setClientId(GOOGLEAPPS_CLIENT_ID);
$client->setApplicationName(SITE_NAME);
$key = file_get_contents(APPLICATION_PATH . 'googleapps-privatekey.p12');
$assertion = new Google_AssertionCredentials(
GOOGLEAPPS_EMAIL_ADDRESS, // the service account name
array('https://www.googleapis.com/auth/admin.directory.user'), // see https://developers.google.com/admin-sdk/directory/v1/guides/authorizing
$key);
$client->setAssertionCredentials($assertion);
$service = new Google_DirectoryService($client);
$user = $service->users->get('email#example.com');
I followed the instructions https://developers.google.com/admin-sdk/directory/v1/guides/prerequisites
and ticked Enable API Access. I used the Google APIs console https://code.google.com/apis/console to generate a Service Account key and got that working OK.
https://groups.google.com/forum/#!msg/google-api-php-client/LM-mwmuZe7I/IA_K5v1R1UMJ
I used the Google PHP library and followed the instructions https://code.google.com/p/google-api-php-client/wiki/OAuth2?hl=no#Service_Accounts to try and get service accounts working. Debugging into their code: I'm authorising fine and getting a fresh Access token as expected https://developers.google.com/accounts/docs/OAuth2ServiceAccount.
I can't figure out why I'm getting the "Not Authorized to access this resource/api" message when everything I have read says I've switched it all on OK. Any ideas?
Just got it working. You need to include the user email of the admin so oAuth authorizes you for that user. Try
$assertion = new Google_AssertionCredentials(
GOOGLEAPPS_EMAIL_ADDRESS, // the service account name
array('https://www.googleapis.com/auth/admin.directory.user'), // see https://developers.google.com/admin-sdk/directory/v1/guides/authorizing
$key,
'notasecret',
'http://oauth.net/grant_type/jwt/1.0/bearer',
'admin_user#email.com'
);
Also after that you need to authorize the client_id for the scope you are requesting from Admin console->Security->Advanced Settings->Authentication->Manage OAuth Client access
I was having a similar problem. I'm using the .NET libraries. The [DriveService][1] example was missing a parameter when creating the provider: ServiceAccountUser, which appears to have to be the email address of an ADMIN. I missed that it was an admin and was getting:
Not Authorized to access this resource/api [403]
as soon as I switched it to an admin account, it worked. I'm afraid I don't speak PHP but I hope this helps.
If you get an error
Class 'Google_AssertionCredentials' not found
you are using the newer libraries, and Google_AssertionCredentials is now Google_Auth_AssertionCredentials.
See:
https://github.com/google/google-api-php-client/blob/master/src/Google/Auth/AssertionCredentials.php
Did you grant the service account access to the given scopes within your Control Panel? See the instructions in the Drive SDK and substitute in the Admin SDK scopes as needed.