Service Account Domain Delegation unauthorized_client - php

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

Related

Google Calendar Api. cannot connect to other user calendar

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.

How to get Business Locations (and Reviews) via Service Account authentication

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.

Calling a google apps script execution api from PHP using a service account

I'm trying to call a very simple google apps script from php using a service account so that only my server can access it, not users of the website.
Here is how I do. I create the script here https://script.google.com
function get() {
return ContentService.createTextOutput('get method');
}
and a new project is automatically associated when i save it.
Then I open File > Project Properties to get the scriptId = MM8zQqofS1OIcnFiNSlm1CGEl5qMrMVBt
I access the developer console of the associated project threw Resources > Project Developers console by clicking on the project link at the top of the popup displayed.
Then I click 'Activate and manage API' and activate the 'Google Apps Script Execution API'. I click on 'Credentials' and see that the previous operation automatically created OAuth2 credentials. But what I need is service account credentials. Then I create one Add credentials > Service account and download generated p12 file. I get the clientId = 109160023321840004240 and clientMail = account-1#project-id-uokwrcpiqeewhwvpdhb.iam.gserviceaccount.com for this service account.
I go back to my script and share it with the service account email with read&write access File > Share. First of all i get an email in my personal mailbox which notifies me that
Delivery to the following recipient failed permanently:
account-1#project-id-uokwrcpiqeewhwvpdhb.iam.gserviceaccount.com
Then I publish the script as an execution API Publish > Publish as an execution API with access to everybody.
Now lets go on the PHP server side. Using the 'Google APIs Client Library for PHP' available here https://github.com/google/google-api-php-client I try to call my script function from PHP:
$client = new Google_Client();
$client->setClientId('109160023321840004240');
$client->setApplicationName('myScript');
$cred = new Google_Auth_AssertionCredentials(
'account-1#project-id-okwrcpiqeewhwvpdhb.iam.gserviceaccount.com',
[/*no scope nedeed for this simple script*/],
file_get_contents('path_to_myScript.p12')
);
$client->setAssertionCredentials($cred);
if ($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion($cred);
}
$service = new Google_Service_Script($client);
$scriptId = 'MM8zQqofS1OIcnFiNSlm1CGEl5qMrMVBt';
// Create an execution request object.
$request = new Google_Service_Script_ExecutionRequest();
$request->setFunction('get');
$response = $service->scripts->run($scriptId, $request);
And here is the response I get all the time
Error calling POST https://script.googleapis.com/v1/scripts/MM8zQqofS1OIcnFiNSlm1CGEl5qMrMVBt:run: (403) The caller does not have permission
If, when I deploy the script, I choose to give access to 'Me only', i get the following response.
Error calling POST https://script.googleapis.com/v1/scripts/MM8zQqofS1OIcnFiNSlm1CGEl5qMrMVBt:run: (404) Requested entity was not found.
I would be so happy if one of you have an idea to help me :)
apps script does not yet support service accounts with execution api. see https://code.google.com/p/google-apps-script-issues/issues/detail?id=5461
google said they are looking into it but apparently wont happen soon (based on google replies on google+ posts about this like https://plus.google.com/+MartinHawksey/posts/Zquix9XqzkK)

{ "error" : "invalid_grant" } error with Google Directory API PHP Client SDK

So I am trying all day already and I just can't seem to correctly authenticate to the google API. This is what I did to set up a connection so far:
I first created a service account for my application
Then I added that service account in the third party client access settings on the admin page for our Google Apps domain. I added the scopes for users and groups
I generated a new Client ID for web applications
I downloaded the .p12 file, the secret JSON file for my web Client ID and stored them locally
So I think that's all I need to succesfully authenticate.. I then used the following code to set everything up:
$this->client = new Google_Client();
$this->client->setAuthConfigFile(STORAGE_PATH.'client_secrets.json');
$this->client->addScope(static::$scopes);
$cred = new Google_Auth_AssertionCredentials(
static::$service_account_email,
static::$scopes,
file_get_contents(STORAGE_PATH.'TRICS-key.p12'));
$cred->sub = static::$delegated_admin;
$this->client->setAssertionCredentials($cred);
$this->directory_service = new Google_Service_Directory($this->client);
Does someone know if I am forgetting something?
Oops. I was a fool. I accidentally used the email of the Web Client instead of the service account email. :') The rest of the code seems to function as it should.

Google Apps Admin SDK Directory API 403 in PHP

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.

Categories