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

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.

Related

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...

Google Calendar API error redirect_uri_mismatch

I am trying to use the google API to manage the user´s calendar, and I am finding a problem. I created and configured a google project on the Google Developers Console. One of the settings was the allowed redirecting uris... and I think it is ok, because after some test where google threw the same error (redirect_uri_mismatch), I got that google ask me for permissions... the problem I think is this line: $this->client->authenticate($_GET['code']);
I am going to show the code and explain what it does
function __construct()
{
parent::__construct();
require __DIR__ . '/vendor/autoload.php';
define('APPLICATION_NAME', 'Google Calendar API PHP Quickstart');
define('CLIENT_SECRET_PATH', __DIR__ . '/credentials/client_secret.json');
define('CREDENTIALS_PATH', __DIR__ .'/credentials/');
define('SCOPES', implode(' ', array(Google_Service_Calendar::CALENDAR_READONLY)));
// If modifying these scopes, delete your previously saved credentials
// at ~/.credentials/calendar-php-quickstart.json
$this->client = new Google_Client();
$this->client->setApplicationName(APPLICATION_NAME);
$this->client->setScopes(SCOPES);
$this->client->setAuthConfigFile(CLIENT_SECRET_PATH);
if (!file_exists(CLIENT_SECRET_PATH.$this->session->userdata("identity").".json") && !$this->input->get("code"))
$this->getCredentials();
}
public function responseCredentials()
{
$authCode = $this->input->get("code");
$this->client->authenticate($_GET['code']);
$accessToken = $this->client->client->getAccessToken();
$credentialsPath = CLIENT_SECRET_PATH.$this->session->userdata("identity").".json";
mkdir(dirname($credentialsPath), 0700, true);
file_put_contents($credentialsPath, $accessToken);
redirect(base_url("dashboard"));
}
private function getCredentials()
{
$this->client->setRedirectUri(base_url('calendar/responseCredentials'));
$authUrl = $this->client->createAuthUrl();
header('Location: ' . filter_var($authUrl, FILTER_SANITIZE_URL));
}
Ok... the first... the constructor it load the google api autoloader, and the constants, creates a new Google_Client object, and inspect if exists a permissions file for the user and there is no "code" index on the get.
If not it invokes the getCredentials function that redirect to google.
After give permissions, the user is redirect to http://domain.com/calendar/responseCredentials (that it is configured on the console.developers.google)
The error thrown is this:
Fatal error: Uncaught exception 'Google_Auth_Exception' with message
'Error fetching OAuth2 access token, message: 'redirect_uri_mismatch'' in
/var/www/html/prototipo/application/controllers/vendor/google/apiclient/src/Google/Auth/OAuth2.php:126
Stack trace:
#0 /var/www/html/prototipo/application/controllers/vendor/google/apiclient/src/Google/Client.php(128): Google_Auth_OAuth2->authenticate('4/rkAKNAmiVgs1Z...', false)
#1 /var/www/html/prototipo/application/controllers/calendar.php(52): Google_Client->authenticate('4/rkAKNAmiVgs1Z...')
#2 [internal function]: Calendar->responseCredentials()
#3 /var/www/html/prototipo/system/core/CodeIgniter.php(360): call_user_func_array(Array, Array)
#4 /var/www/html/prototipo/index.php(202): require_once('/var/www/html/p...')
#5 {main} thrown in/var/www/html/prototipo/application/controllers/vendor/google/apiclient/src/Google/Auth/OAuth2.php on line 126
What am I doing wrong??
Thank you.
EDIT
I just realized that at the end of the code variable on the return uri there always is a pad... something like this:
http://pedro.eatec.es/prototipo/calendar_test_stack/responseCredentials?code=4/PL7nK1s9m5vpBow7HScaPmkpWpoW3J4uzUxlD7NE49g#
The example here: https://developers.google.com/identity/protocols/OAuth2WebServer#handlingresponse doesn´t show this pad... I tried to do this:
$this->client->authenticate($_GET['code']."#");
But... of course, doesn´t work.
PS: I tried to do it because with echo $_GET['code']; didn´t show the pad.
Hello and Thanks #thepieterdc finally you were reason...
I was setting up correctly the project on console.developers... but my mistake was that I need make some trying to get a correct configuration and when I got to make disappear the error 400 (with the broken robot) and it ask me for permission, on the redirecting function when I make $this->g_client->authenticate($_GET['code']); the code try to make other request (on OAuth2.php) to https://accounts.google.com/o/oauth2/token and it use the client_id.json that you need to refresh... and I didn´t. I WAS USING THE FIRST EDITION OF THE CLIENT_ID.JSON I need to re-download (or re-write) if you change something on the console.
Thanks.

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

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.

Create google calendar events with php and service account - authenticate issue

Is it possible to access google calendar service while using service-account-method?
Google says indirectly, it is not possible, because calendar-service is not on the list of supported services in the documentation of service-account-method, but I personally think, it IS possible.
But how?
I am writing a calendar application in php, and there I want to create calendar events into my google-calendar without user-action (e.g. login).
I learned, that first the application has to authenticate itself against google server, using the service-account-method with a key-file .p12
I am using the following code for authentication:
(downloaded fom here: http://code.google.com/p/google-api-php-client/source/browse/trunk/examples/prediction/serviceAccount.php )
session_start();
require_once 'google-api/src/Google_Client.php';
require_once 'google-api/src/contrib/Google_CalendarService.php';
require_once 'google-api/src/contrib/Google_PredictionService.php';
$client = new Google_Client();
$client->setApplicationName(GOOGLE_APPLICATION_NAME);
$client->setClientId(GOOGLE_CLIENT_ID);
$keyfile = file_get_contents(GOOGLE_KEY_FILE);
$client->setAssertionCredentials(new Google_AssertionCredentials(
GOOGLE_SERVICE_ACCOUNT_NAME,
array('https://www.googleapis.com/auth/prediction'),
$keyfile)
);
But this login seems not to work.
How do I find out, if server is logged in at that moment?
I want to continue with this:
$cal = new Google_CalendarService($client);
if (isset($_SESSION['token'])) {
$client->setAccessToken($_SESSION['token']);
}
if ($client->getAccessToken()) {
$calList = $cal->calendarList->listCalendarList(); // <- this is line 55
print "<h1>Calendar List</h1><pre>" . print_r($calList, true) . "</pre>";
$_SESSION['token'] = $client->getAccessToken();
} else {
$authUrl = $client->createAuthUrl();
print "<a class='login' href='$authUrl'>Connect Me!</a>";
}
But in line 55 there comes this error:
Fatal error: Uncaught exception 'Google_ServiceException' with message
'Error calling GET
https://www.googleapis.com/calendar/v3/users/me/calendarList: (403)
Insufficient Permission' in
/usr/www/users/leuchtk/html/google-api/src/io/Google_REST.php:66
Stack trace: #0
/usr/www/users/leuchtk/html/google-api/src/io/Google_REST.php(36):
Google_REST::decodeHttpResponse(Object(Google_HttpRequest))
#1 /usr/www/users/leuchtk/html/google-api/src/service/Google_ServiceResource.php(186):
Google_REST::execute(Object(Google_HttpRequest))
#2 /usr/www/users/leuchtk/html/google-api/src/contrib/Google_CalendarService.php(205):
Google_ServiceResource->__call('list', Array)
#3 /usr/www/users/leuchtk/html/i_termine_admin.php(55): Google_CalendarListServiceResource->listCalendarList()
#4 /usr/www/users/leuchtk/html/termine_admin.php(113): include('/usr/www/users/...')
#5 {main} thrown in /usr/www/users/leuchtk/html/google-api/src/io/Google_REST.php on line 66
So it looks like, the application is not logged in.
I am completely lost in this code for now.
Thank you for some little light, what is missing there...
Marco
You may want to refer to this question. Your issue could be just to add the
array('https://www.googleapis.com/auth/calendar', 'https://www.googleapis.com/auth/calendar.readonly'),
in where you call the
$client->setAssertionCredentials();
Google PHP Client API: Insufficient Permission
Hope this helps

Public stream to facebook's user wall with php?

I build a facebook app with php api, everything work fine just have a problem when i need public a message on user's Wall.
my code bellow
$appapikey = "xxxxxx";
$appsecret = "xxxxxx";
$facebook = new Facebook($appapikey, $appsecret);
$fb_user = $facebook->require_login();
if (!$facebook->api_client->users_hasAppPermission("publish_stream, status_update")){
echo '<fb:prompt-permission perms="publish_stream, status_update">Click here to grant permissions to update your status and publish to your stream.</fb:prompt-permission>';
try {
$facebook->api_client->stream_publish($message);
} catch (Exception $e) {
echo "Public error".$e->getMessage();
}
}
I had allow Permission for publish_stream but still get error
Uncaught exception 'FacebookRestClientException' with message 'Unauthorized source IP address (ip was: 69.89.31.xxx)'
Stack trace:
#0 /home/flexvnne/public_html/facebook/facebook/client/facebookapi_php5_restlib.php(345): FacebookRestClient->call_method('facebook.users....', Array)
#1 /home/flexvnne/public_html/facebook/index.php(36): FacebookRestClient->users_getInfo('625757897', 'username')
#2 {main}
thrown in /home/flexvnne/public_html/facebook/facebook/client/facebookapi_php5_restlib.php on line 1314
[16-Oct-2009 01:30:53] PHP Fatal error: Uncaught exception 'FacebookRestClientException' with message 'Unauthorized source IP address (ip was: 69.89.31.xxx)' in /home/flexvnne/public_html/facebook/facebook/client/facebookapi_php5_restlib.php:1314
Anyone known way to solved that problem ?
It looks like your users_getInfo() call is the one that is failing here, not stream publishing.
My guess is check your whitelist/blacklist in your facebook developer application app settings -- your IP might be restricted.

Categories