(400) Bad Request using Google API PHP Client with the Admin SDK - php

I'm trying to use the Google API PHP Client with the Google Directory API. I went into the Google Developers Console and created a project called google-sync. I then enabled the Admin SDK in the APIs list page. I then selected "Create new Client ID" from the Credentials page, and selected Service Account, and then downloaded the .bin private key that I was prompted to download. I then also clicked on "Generate new P12 key" and downloaded the .p12 file, which was placed in the same directory as the PHP file.
Here's my PHP code (which follows this part of the docs) that is trying to list all users.
<?php
session_start();
require 'vendor/autoload.php';
$SCOPE = 'https://www.googleapis.com/auth/admin.directory.user https://www.googleapis.com/auth/admin.directory.group https://www.googleapis.com/auth/admin.directory.orgunit';
$SERVICE_ACCOUNT_EMAIL = '<EMAIL ADDRESS>';
$SERVICE_ACCOUNT_PKCS12_FILE_PATH = '<P12 FILE NAME>.p12';
$client = new Google_Client();
$client->setApplicationName('google-sync');
$adminService = new Google_Service_Directory($client);
$key = file_get_contents($SERVICE_ACCOUNT_PKCS12_FILE_PATH);
$cred = new Google_Auth_AssertionCredentials(
$SERVICE_ACCOUNT_EMAIL,
array($SCOPE),
$key);
$client->setAssertionCredentials($cred);
$allUsers = $adminService->users->listUsers();
When I run this code, I get this error:
PHP Fatal error: Uncaught exception 'Google_Service_Exception' with message 'Error calling GET https://www.googleapis.com/admin/directory/v1/users: (400) Bad Request' in /projects/google-sync/vendor/google/apiclient/src/Google/Http/REST.php:80
Stack trace:
#0 /projects/google-sync/vendor/google/apiclient/src/Google/Http/REST.php(44): Google_Http_REST::decodeHttpResponse(Object(Google_Http_Request))
#1 /projects/google-sync/vendor/google/apiclient/src/Google/Client.php(499): Google_Http_REST::execute(Object(Google_Client), Object(Google_Http_Request))
#2 /projects/google-sync/vendor/google/apiclient/src/Google/Service/Resource.php(195): Google_Client->execute(Object(Google_Http_Request))
#3 /projects/google-sync/vendor/google/apiclient/src/Google/Service/Directory.php(2063): Google_Service_Resource->call('list', Array, 'Google_Service_...')
#4 /projects/google-sync/auth-test.php(20): Google_Service_Directory_Users_Resource->listUsers()
#5 {main}
thrown in /projects/google-sync/vendor/google/apiclient/src/Google/Http/REST.php on line 80
Fatal error: Uncaught exception 'Google_Service_Exception' with message 'Error calling GET https://www.googleapis.com/admin/directory/v1/users: (400) Bad Request' in /projects/google-sync/vendor/google/apiclient/src/Google/Http/REST.php on line 80
Google_Service_Exception: Error calling GET https://www.googleapis.com/admin/directory/v1/users: (400) Bad Request in /projects/google-sync/vendor/google/apiclient/src/Google/Http/REST.php on line 80
Call Stack:
0.0001 232296 1. {main}() auth-test.php:0
0.0172 2957992 2. Google_Service_Directory_Users_Resource->listUsers() /projects/google-sync/auth-test.php:20
0.0172 2959144 3. Google_Service_Resource->call() /projects/google-sync/vendor/google/apiclient/src/Google/Service/Directory.php:2063
0.3356 2970752 4. Google_Client->execute() /projects/google-sync/vendor/google/apiclient/src/Google/Service/Resource.php:195
0.3356 2971568 5. Google_Http_REST::execute() /projects/google-sync/vendor/google/apiclient/src/Google/Client.php:499
0.7015 2974424 6. Google_Http_REST::decodeHttpResponse() /projects/google-sync/vendor/google/apiclient/src/Google/Http/REST.php:44
When I downloaded the p12 file, I was given a password associated with the private key, but I'm unable to find any documentation on how that password should be included. Is this my problem?

I was facing the same issue. Service account should impersonate a domain admin when it makes the request. In addition, listUsers() expects the domain to be passed as an argument.
Makes sure that you've delegated domain-wide authority to the service account - https://developers.google.com/api-client-library/php/auth/service-accounts
$cred = new Google_Auth_AssertionCredentials(
$service_account_name,
array($SCOPE),
$key
);
$cred->sub = "admin#domain.com";
//Get All users.
$list = $service->users->listUsers(Array('domain' => 'domain.com'));
//Get one user
$userId = $service->users->get('someuser#domain.com');

I was able to fix this by going into my domain's Admin Console, went to the Manage API client access page under Security, and added the Client Id from the Developer Console and added the scopes I needed for the Directory API.
See this part of the docs for more info.

Related

Error validate an ID token in PHP - Google API

I am using the following example backend-auth Google
<?php
require_once 'Google/vendor/autoload.php';
$CLIENT_ID = "xxxxxxxxxx";
// Get $id_token via HTTPS POST.
$client = new Google_Client(['client_id' => $CLIENT_ID]); // Specify the CLIENT_ID of the app that accesses the backend
$payload = $client->verifyIdToken($id_token);
if ($payload) {
$userid = $payload['sub'];
// If request specified a G Suite domain:
//$domain = $payload['hd'];
} else {
// Invalid ID token
}
?>
I have already created the credentials, API, and OAUTH2
API_KEY: AIzaAsDfGuYn6nk9761kvnwMxns-PPeO1Ka1YsA
CLIENT_ID: 15123456862-94jrd0d2lis29lbl6dekpk0fp4otgm8r.apps.googleusercontent.com
CLIENT_SECRET: qertf3l3UfgdhjiWEREZI8xN
But it generates the following error:
Notice: Undefined variable: id_token in C:\Adsense\index.php on line 10
Fatal error: Uncaught LogicException: id_token must be passed in or set as part of setAccessToken in C:\Adsense\Google\vendor\google\apiclient\src\Client.php:784 Stack trace: #0 C:\Adsense\index.php(10): Google\Client->verifyIdToken(NULL) #1 {main} thrown in C:\Adsense\Google\vendor\google\apiclient\src\Client.php on line 784
I have searched this forum in the google documentation and in the google console panel but I cannot find a fixed token or how to create it, I cannot find references
https://oauth2.googleapis.com/tokeninfo?id_token=XXXXX
It's a bit of an old post, but for anyone like me and the OP struggling with this, it's actually quite a simple solution.
The example code has a commented out line that reads
// Get $id_token via HTTPS POST.
You actually have to write this code. Using the worked examples from Google, the JavaScript function passes the authentication token as idtoken.
$id_token = $_POST['idtoken'];
Will do the trick. You'll probably want to perform some basic error checking, for example,
if (isset($_POST['idtoken'])){
$id_token = $_POST['idtoken'];
$payload = $client->verifyIdToken($id_token);
...

How do I connect to private google calendar with PHP

I'm not very good with PHP, and I am trying to create a webpage where I will navigate to the page and it will show a list of events from my private google calendar. This used to work years ago, but Google has changed the API so my old solution is broken. I saw this thread:
How do I connect to the Google Calendar API without the oAuth authentication?
and I tried it, but it looks like that method also doesn't work anymore. (When I say "doesn't work" I mean that I currently have the latest google-api-php-client-2.0.3 installed at public_html/includes/google-api-php-client-2.0.3/. I found the client.php referenced in the above link, but the other files are not in the new API.
Basically, I am trying to figure out what the PHP would look like to achieve what you can do on this page when you put in your calendar ID:
https://developers.google.com/google-apps/calendar/v3/reference/events/list#request
So I think this is a two step process: Authenticate and then print the output. The trouble I'm having is in authenticating.
I have tried this:
<?php
session_start();
require_once "/includes/google-api-php-client-2.0.3/src/Google/client.php";
require_once "/includes/google-api-php-client-2.0.3/src/contrib/Google_CalendarService.php";
const CLIENT_ID = '...';
const SERVICE_ACCOUNT_NAME = 'my service account name';
// Make sure you keep your key.p12 file in a secure location, and isn't
// readable by others.
const KEY_FILE = '...';
$client = new Google_Client();
$client->setApplicationName("...");
if (isset($_SESSION['token'])) {
$client->setAccessToken($_SESSION['token']);
}
// Load the key in PKCS 12 format (you need to download this from the
// Google API Console when the service account was created.
$key = file_get_contents(KEY_FILE);
$client->setAssertionCredentials(new Google_AssertionCredentials(
SERVICE_ACCOUNT_NAME,
array('https://www.googleapis.com/auth/calendar', "https://www.googleapis.com/auth/calendar.readonly"),
$key)
);
$client->setClientId(CLIENT_ID);
$service = new Google_CalendarService($client);
//Save token in session
if ($client->getAccessToken()) {
$_SESSION['token'] = $client->getAccessToken();
}
//And now you can use the code in their PHP examples, like: $service->events->listEvents(...)
?>
But I get error:
Warning: require_once(/includes/google-api-php-client-2.0.3/src/Google_Client.php): failed to open stream: No such file
Because the API seems to have changed.
I found this link:
https://developers.google.com/identity/protocols/OAuth2ServiceAccount
I have created a service account, and downloaded a private key but I don't know what to do with it :-/
I tried this:
https://developers.google.com/api-client-library/php/auth/web-app
But when I navigate to the index.php I get this error:
Fatal error: Uncaught exception 'InvalidArgumentException' with message 'file does not exist' in /home/xxx/public_html/includes/google-api-php-client-2.0.3/src/Google/Client.php:841 Stack trace: #0 /home/xxx/public_html/testing_oauth.php(7): Google_Client->setAuthConfig('client_secrets....') #1 {main} thrown in /home/xxx/public_html/includes/google-api-php-client-2.0.3/src/Google/Client.php on line 841
I tried hard coding this into the index.php example (line 103-107):
// https://developers.google.com/console
'client_id' => 'My service accounts project name',
'client_secret' => 'url link to my client_secret.json file',
'redirect_uri' => null,
'state' => null,
But I get the same error...

Adding User to Chef via Chef Server API

I am attempting to create a user on my Chef Server through the Chef Server API. I am currently using a PHP wrapper for the API interface which can be found here.
I understand that in order to create a user using the API, you must provide the pivotal.pem file as well as the pivotal username.
Here is a snippet of my PHP code that I am using:
// ENVIRONMENT VARIABLES
// The URL for the Chef Server
$server = "mycompany.com";
// The name used when authenticating
$client = 'pivotal';
// The location of the file which contains the client key
$key = "../../../pivotal.pem";
// The version of the Chef Server API that is being used
$version = "12.0.2";
// Create a Chef object
$chef = new Chef($server, $client, $key, $version);
// API Request
$createUserRequest = array("name"=>$displayName, "display_name"=>$displayName, "email"=>$emailAddress, "password"=>$password);
$createUserRequest = json_encode($createUserRequest);
$chef->post('/users/', $createUserRequest);
Here is the reponse that I receive from the server:
Fatal error: Uncaught exception 'Exception' with message 'Invalid signature for user or client 'pivotal'' in C:\Workspace\SA_SSAF\app\plugin\CHEF\Chef PHP\src\Jenssegers\Chef\Chef.php:187
Stack trace:
#0 C:\..\..\app\plugin\CHEF\Chef PHP\src\Jenssegers\Chef\Chef.php(70): Jenssegers\Chef\Chef->api('/users/', 'POST', '{"name":"entra"...')
#1 C:\..\..\app\plugin\CHEF\controller\chefEnrollUser.php(55): Jenssegers\Chef\Chef->post('/users/', '{"name":"entra"...')
#2 {main}
thrown in C:\..\..\app\plugin\CHEF\Chef PHP\src\Jenssegers\Chef\Chef.php on line 187
If I try and perform a GET request using the same configuration, I receive a successful response.
Any clues as to why something like this may be happening?
Thanks

"Access denied" exception is thrown, though the account has access

I'm using a service account to delegate domain wide security in order to pull a user listing from our Google Apps for Education instance via the Directory API and the PHP client library.
I'm fairly certain my service account has all the correct security because it's able to pull a listing using the API reference's "try it" feature.
So, at this point, everything is pointing toward an issue with my code but I can't seem to figure out where:
<?php
require 'vendor/autoload.php';
$clientEmail = '<>#developer.gserviceaccount.com';
$privateKey = file_get_contents(__DIR__ . '/access.p12');
$scopes = array(
'https://www.googleapis.com/auth/admin.directory.user.readonly',
);
$credentials = new Google_Auth_AssertionCredentials($clientEmail, $scopes, $privateKey);
$credentials->sub = 'service.account#my.domain';
$client = new Google_Client();
$client->setAssertionCredentials($credentials);
if ($client->getAuth()->isAccessTokenExpired())
{
$client->getAuth()->refreshTokenWithAssertion();
}
$directory = new Google_Service_Directory($client);
$result = $directory->users->listUsers(array('domain' => 'my.domain'));
var_dump($result);
The code above throws the following error:
Fatal error: Uncaught exception 'Google_Auth_Exception' with message 'Error refreshing the OAuth2 token, message: ' in C:\wamp\www\quick\vendor\google\apiclient\src\Google\Auth\OAuth2.php on line 358
Google_Auth_Exception: Error refreshing the OAuth2 token, message: '{
"error" : "access_denied",
"error_description" : "Requested client not authorized."
}' in C:\wamp\www\quick\vendor\google\apiclient\src\Google\Auth\OAuth2.php on line 358
Call Stack:
0.0010 132792 1. {main}() C:\wamp\www\quick\index.php:0
0.0260 1060248 2. Google_Auth_OAuth2->refreshTokenWithAssertion() C:\wamp\www\quick\index.php:18
0.9230 1163560 3. Google_Auth_OAuth2->refreshTokenRequest() C:\wamp\www\quick\vendor\google\apiclient\src\Google\Auth\OAuth2.php:309
The call stack should identify the specific line where this error occurred. Note that the second line in the stack seems to point to line 18 of your script, where the code indeed relates to OAuth verification:
$client->getAuth()->refreshTokenWithAssertion();
In other words, when you try to refreshTokenWithAssertion, Google says "access_denied because Requested client not authorized". If you're trying to identify where in your script you hit the error, I think that should answer your question.
If you want to figure out why it got an error, I'd do some google searches for refreshTokenWithAssertion plus that error message and see if you find any other developers working through a similar problem. For example by doing that google search I found this other page on SO that may help you.
Good luck!

authentication Google Content Api service account - error 'user cannot access account'

I am bashing my head against the wall trying to get my code to work.
I already have succesfully connected to the google Api by using the authentication route with the redirect url.
However, I need to get this working as a standalone service which will be running in a crontab.
So now I am trying to authenticate with a 'service account'.
This is my code and below that you will find the error it is giving me.
$client = new Google_Client();
$client->setApplicationName('GoogleShoppingService');
if (isset($_SESSION['service_token'])) {
$client->setAccessToken($_SESSION['service_token']);
}
$service = new Google_Service_Content($client);
$client_id = 'xxxxxxx.apps.googleusercontent.com';
$client->setClientId($client_id);
$service_account_name = 'xxxxxxx#developer.gserviceaccount.com';
$key_file_location = 'privatekey.p12';
$key = file_get_contents($key_file_location);
$scope = 'https://www.googleapis.com/auth/content';
$cred = new Google_Auth_AssertionCredentials(
$service_account_name,
array($scope),
$key
);
$result = $client->setAssertionCredentials($cred);
print_r($result);
if($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion($cred);
}
$_SESSION['service_token'] = $client->getAccessToken();
echo $client->getAccessToken();
$merchantId = 1234567;//this a dummy value, I replace it with the actual merchantId
$accountId = 1234567;//this a dummy value, I replace it with the actual accountId
$accountstatuses = $service->accountstatuses->get($merchantId,$accountId);
So this is the message I get when running the code. (note that the token is created, but that I am not able to access the content of the Google Shopping feed.)
{"access_token":"ya29.NQD7MQz0cas9PhoAAADRPMlTVecqYXYh4fNoZfRMymQtSF4hwqJn31uobohLbw","expires_in":3600,"created":1404200605}
Fatal error:
Uncaught exception 'Google_Service_Exception' with message 'Error calling GET https://www.googleapis.com/content/v2/1234567/accountstatuses/1234567: (401) User cannot access account 1234567' in /home/sites/site1/web/googleShopping2/src/Google/Http/REST.php:79
Stack trace:
#0 /home/sites/site1/web/googleShopping2/src/Google/Http/REST.php(44): Google_Http_REST::decodeHttpResponse(Object(Google_Http_Request))
#1 /home/sites/site1/web/googleShopping2/src/Google/Client.php(499): Google_Http_REST::execute(Object(Google_Client), Object(Google_Http_Request))
#2 /home/sites/site1/web/googleShopping2/src/Google/Service/Resource.php(195): Google_Client->execute(Object(Google_Http_Request))
#3 /home/sites/site1/web/googleShopping2/src/Google/Service/Content.php(685): Google_Service_Resource->call('get', Array, 'Google_Service_...')
#4 /home/sites/site1/web/googleShopping2/examples/test.php(58): Google_Service_Content_Accountstatuses_Resource->get(1234567, 1234567)
#5 {main} thrown in /home/sites/site1/web/googleShopping2/src/Google/Http/REST.php on line 79
I've already tried to find a solution for 2 days now, but any hint that I've found doesn't help me. I've also creted a new project with new Api auth keys, but nothing works and I always get the above message.
Who can help me please?
Regards,
Martin
You need to add the email address of the service account you created to the Google merchant account under Settings > User.
On https://merchants.google.com/
At the top right, click on the gear icon i.e settings.
click on account access
click +add user
add the email-adress you got from the service account .json file. (it's in there)
make sure the added user is set to admin.

Categories