403 Error in calling Google Admin SDK - php

I am trying to list the users in my google domain using the Admin SDK PHP library. However I am getting 403 users when I am trying to list my users. This is what I tried
$client = new Google_Client();
$client->setApplicationName("My Application");
$credential = new Google_Auth_AssertionCredentials(
$serviceAccount,
array('https://www.googleapis.com/auth/admin.directory.user'),
$privateKey,
'notasecret',
'http://oauth.net/grant_type/jwt/1.0/bearer'
);
$client->setAssertionCredentials($credential);
if($client->getAuth()->isAccessTokenExpired())
{
$client->getAuth()->refreshTokenWithAssertion($credential);
}
$service = new Google_Service_Directory($client);
$optParams = array('domain' => 'mydomain');
$results = $service->users->listUsers($optParams);
But I get this 403 error
Error calling GET https://www.googleapis.com/admin/directory/v1/users?domain=mydomain: (403) Not Authorized to access this resource/api
As suggested in other similar posts, I also tried including the delegated admin as shown below
$credential = new Google_Auth_AssertionCredentials(
$serviceAccount,,
array('https://www.googleapis.com/auth/admin.directory.user'),
$privateKey,
'notasecret',
'http://oauth.net/grant_type/jwt/1.0/bearer',
'admin#mydomain.com'
);
But this gave the following error on refreshTokenWithAssertion($credential)
Error refreshing the OAuth2 token, message: '{
"error" : "unauthorized_client",
"error_description" : "Unauthorized client or scope in request."
}'
I verified the service account and also enabled the API in the project's console.Can anyone figure out what I am doing wrong ? Please help. I am struct at this for a while.

I found the solution for this error. I added the 'sub' in the Google_Auth_AssertionCredentials as shown below and added the Client Id and the scope at admin.google.com->Security->Manage API access and Authorized it.
This
$credential = new Google_Auth_AssertionCredentials(
$serviceAccount,,
array('https://www.googleapis.com/auth/admin.directory.user'),
$privateKey,
'notasecret',
'http://oauth.net/grant_type/jwt/1.0/bearer',
'admin#mydomain.com', false
);
plus authorization at admin.google.com->Security->Manage API access solved the issue. Why I had to authorize is a different question.

Related

Get "Not authorized to access the application ID" after using Google Apps Marketplace API

I have a web app and trying to find out which users in google domain have installed my app. I've tried to use code from here: Determine if a google user's domain has my marketplace app installed, but it doesn't works. I am still getting error "(403) Not authorized to access the application ID" in response.
Code:
$private_key = file_get_contents('path_to_p.12_key');
$service_account_name = '{service_acc_name}'; // name from developers console
$cred = new Google_Auth_AssertionCredentials($service_account_name, array('https://www.googleapis.com/auth/appsmarketplace.license'), $private_key);
$client = new Google_Client();
$client->setAssertionCredentials($cred);
$url = "https://www.googleapis.com/appsmarket/v2/licenseNotification/{appID}";
$httpRequest = new Google_Http_Request($url, 'GET');
$httpRequest->setBaseComponent($client->getBasePath());
$httpRequest = $client->getAuth()->sign($httpRequest);
try
{
$result = $client->execute($httpRequest);
}
catch (Exception $e)
{
echo $e->getMessage();
}
I've also added https://www.googleapis.com/auth/appsmarketplace.license scope in project settings in developers console.
I can't get what's wrong.
OK, I've solved it. You must add all scopes to your service account object that used by your app (not just that scopes you are really want to use by service account):
$cred = new Google_Auth_AssertionCredentials($service_account_name, array('https://www.googleapis.com/auth/userinfo.email', 'https://www.googleapis.com/auth/userinfo.profile', 'https://www.googleapis.com/auth/admin.directory.user.readonly', 'https://www.googleapis.com/auth/admin.directory.user', 'https://www.googleapis.com/auth/appsmarketplace.license'), $private_key);

Error refreshing the OAuth2 token, message: '{ "error" : "unauthorized_client", "error_description" : "Unauthorized client or scope in request." }'

When I try to fetch data from Google Analytics, I got error
Error refreshing the OAuth2 token, message: '{ "error" :
"unauthorized_client", "error_description" : "Unauthorized client or
scope in request." }'
I create project in my https://console.developers.google.com/project, create Service account and download .p12 key. Also enable "Analytics API" in project settings, but it doesn't work. This is my code:
$service_account_name = '<Service Email>#developer.gserviceaccount.com';
$key_file_location = '<keyName>.p12';
$key = file_get_contents($key_file_location);
$cred = new Google_Auth_AssertionCredentials(
$service_account_name,
array(Google_Service_Analytics::ANALYTICS),
$key,
'notasecret',
'http://oauth.net/grant_type/jwt/1.0/bearer',
'<My email>'
);
$client->getAuth()->setAssertionCredentials($cred);
$service = new Google_Service_Analytics($client);
$result = $service->data_ga->get("ga:<profileID>", "yesterday", "today", "ga:pageviews");
print_r( $result);
What is wrong with my project? Please help.
You are missing the final step which is giving access to your application in the control panel of your domain.
https://developers.google.com/+/domains/authentication/delegation
You created the service account, now you need to delegate/authorize the application.

Unable to listUserMessages() - 500 Backend Error

When using the below code to attempt to list messages received by a brand new gmail account I just set up, I get
[Google_Service_Exception] Error calling GET https://www.googleapis.com/gmail/v1/users/myGmailAccount%40gmail.com/messages: (500) Backend Error
I know the validation portion is working correctly because I'm able to make minor modifications and query the books api as shown in this example. Below is the code I'm using to attempt to query recent messages received...
const EMAIL = 'myGmailAccount#gmail.com';
private $permissions = [
'https://www.googleapis.com/auth/gmail.readonly'
];
private $serviceAccount = 'xxxxxxxxxxxxxxxxx#developer.gserviceaccount.com';
/** #var Google_Service_Gmail */
private $gmail = null;
/** #var null|string */
private static $serviceToken = null;
public function __construct()
{
$client = new Google_Client();
$client->setApplicationName($this->applicationName);
$this->gmail = new Google_Service_Gmail($client);
//authentication
if (isset(self::$serviceToken)) {
$client->setAccessToken(self::$serviceToken);
}
$credentials = new Google_Auth_AssertionCredentials(
$this->serviceAccount,
$this->permissions,
$this->getKey()
);
$client->setAssertionCredentials($credentials);
if($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion($credentials);
}
self::$serviceToken = $client->getAccessToken();
}
public function getMessages()
{
$this->gmail->users_messages->listUsersMessages(self::EMAIL);
}
I have granted API access to gmail:
The 500 makes me believe this is an internal error with the gmail API or I'm missing something the PHP client isn't validating.
This one work for me. My understanding is service account doesn't have a mailbox and it's not too sure which mailbox it should work on. So you can't use listUsersMessages() function to get all messages.
So you will need to specify which email address that the service account need to work on.
Make sure that the scope has been allowed on Web App API to
1. Add this line:
$credentials->sub = self::EMAIL;
Before:
$client->setAssertionCredentials($credentials);
2. Then Update your getMessages() to:
$this->gmail->users_messages->listUsersMessages("me");
Hope this helps!
I imagine the account has logged in to the web interface already, right? Have you tried with a separate user? How about doing something like labels list instead? Did you try using the APIs explorer site? https://developers.google.com/apis-explorer/#p/gmail/v1/
Can you provide the first 5 digits of the developer's client ID (it's not secret anyway) so I can try to track down the error?
For this to work you have to impersonate an user account (the service account doesn't have a mailbox, as lthh89vt points out).
If you try to access the mailbox directly you will get the (500) Back End error.
The full code is:
$client_email = '1234567890-a1b2c3d4e5f6g7h8i#developer.gserviceaccount.com';
$private_key = file_get_contents('MyProject.p12');
$scopes = array('https://www.googleapis.com/auth/gmail.readonly');
$user_to_impersonate = 'user#example.org';
$credentials = new Google_Auth_AssertionCredentials(
$client_email,
$scopes,
$private_key,
'notasecret', // Default P12 password
'http://oauth.net/grant_type/jwt/1.0/bearer', // Default grant type
$user_to_impersonate,
);
$client = new Google_Client();
$client->setAssertionCredentials($credentials);
if ($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion();
}
$service = new Google_Service_Gmail($client);
$results = $service->users_messages->listUsersMessages('me');
Full instructions can be found on Google APIs Client Library for PHP

Google_Auth_Exception When trying to get OAuth 2.0 Service Account Authentication

This is my code:
session_start();
error_reporting(E_ALL);
ini_set('display_errors', 1);
require_once 'Google/Client.php';
require_once 'Google/Service/AdExchangeSeller.php';
$scriptUri = "http://example.com/some_seller_api.php";
$client_id = 'XXXXXX.apps.googleusercontent.com';
$service_account_name = 'XXXXXXXXX#developer.gserviceaccount.com';
$key_file_location = '/XXXXX/privatekey.p12';
$client = new Google_Client();
$client->setApplicationName("Example_app");
if (isset($_SESSION['service_token'])) {
$client->setAccessToken($_SESSION['service_token']);
}
$key = file_get_contents($key_file_location);
$cred = new Google_Auth_AssertionCredentials(
$service_account_name,
array('https://www.googleapis.com/auth/adexchange.seller.readonly'),
$key
);
$client->setAssertionCredentials($cred);
if($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion($cred);
}
$_SESSION['service_token'] = $client->getAccessToken();
$service = new Google_Service_AdExchangeSeller($client);
$acc = $service->adclients->listAdclients();
I do everything like in official manual and example from https://github.com/google/google-api-php-client/blob/master/examples/service-account.php
And i've got an error:
Fatal error: Uncaught exception 'Google_Auth_Exception' with message 'Error refreshing the OAuth2 token, message: '{ "error" : "access_denied", "error_description" : "Requested client not authorized." }''
What am I doing wrong?
It appears that you haven't authorized your application with the target service. One of the OAuth2 steps is that your application (the one that's going to be accessing the service) needs to be "registered" (or authorized) with the target service. This is the way you will register what's the callback URL, etc.
Per your code, you are accessing the Ad Exchange Seller REST API. Open the following link and follow the step by step guide in order to fix the issue you are having:
https://developers.google.com/ad-exchange/seller-rest/getting_started#auth

Upload file to Google Drive via API

Everyone
I need to upload file to Google Drive via the API, I did exactly what it is mention https://developers.google.com/drive/quickstart-php.
I had generated the access token and saved it in the file, the problem is that it only works for the first time and next time it gives error
OAuth2 token, message: '{ "error" : "invalid_grant" }
We only need to upload files to Google drive (our own account) after getting from the users by form.
I had tried scripts from many tutorial but it didn't seem to work.
I had also tried with offline access permission but still no luck.
Update:
Here it the code that I use to generate access token
require_once APP_PATH.'_includes/google_drive/Google_Client.php';
require_once APP_PATH.'_includes/google_drive/contrib/Google_DriveService.php';
$drive = new Google_Client();
$drive->setClientId('xxxxxxxxxxxxxxxx');
$drive->setClientSecret('xxxxxxxxxxxxxxx');
$drive->setRedirectUri('urn:ietf:wg:oauth:2.0:oob');
$drive->setScopes(array('https://www.googleapis.com/auth/drive'));
$gdrive = new Google_DriveService($drive);
$url = $drive->createAuthUrl();
$authorizationCode = trim(fgets(STDIN));
$token = $drive->authenticate($authorizationCode);
And then I used this code
$drive = new Google_Client();
$drive->setClientId('xxxxxxxxxxx');
$drive->setClientSecret('xxxxxxxxxxxxxxx');
$drive->setRedirectUri('urn:ietf:wg:oauth:2.0:oob');
$drive->setScopes(array('https://www.googleapis.com/auth/drive'));
$gdrive = new Google_DriveService($drive);
$_GET['code']= '4/axxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
file_put_contents('token.json', $drive->authenticate());
$drive->setAccessToken(file_get_contents('token.json'));
$doc = new Google_DriveFile();
$doc->setTitle('Test Document');
$doc->setDescription('Test description');
$doc->setMimeType('text/plain');
$content = file_get_contents('document.txt');
$output = $gdrive->files->insert($doc, array(
'data' => $content,
'mimeType' => 'text/plain',
));
print_r($output);
it works good and but when I run the page again it says
Fatal error: Uncaught exception 'Google_AuthException' with message 'Error fetching OAuth2 access token, message: 'invalid_grant'' in ...Google_OAuth2.php on line 115
any help is appreciated.
Based on #BurcuDogan's comment, commenting out authenticate method resolved the issue.
//file_put_contents('token.json', $drive->authenticate());

Categories