Google Calendar API Service Accounts - Error 403 - php

I have an issue I can't solve. I am trying to insert an event in a public calendar. I managed to do it but I do not want the user to login so I tried the Service Account method but I can't get it working.
Issue:
Fatal error: Uncaught exception 'Google_Service_Exception' with message 'Error calling POST https://www.googleapis.com/calendar/v3/calendars/rentyourparis.com_h4s4cm7b8e27of4oigpl4651co%40group.calendar.google.com/events?key=AIzaSyA5xDFe5UjuleS-pssxoXTLOsT0ZA6dur0: (403) Access Not Configured. Please use Google Developers Console to activate the API for your project.' in /home/rentyour/www/google-api-php-client/src/Google/Http/REST.php:79 Stack trace: #0 /home/rentyour/www/google-api-php-client/src/Google/Http/REST.php(44): Google_Http_REST::decodeHttpResponse(Object(Google_Http_Request)) #1 /home/rentyour/www/google-api-php-client/src/Google/Client.php(505): Google_Http_REST::execute(Object(Google_Client), Object(Google_Http_Request)) #2 /home/rentyour/www/google-api-php-client/src/Google/Service/Resource.php(195): Google_Client->execute(Object(Google_Http_Request)) #3 /home/rentyour/www/google-api-php-client/src/Google/Service/Calendar.php(1459): Google_Service_Resource->call('insert', Array, 'Google_Service_...') #4 /h in /home/rentyour/www/google-api-php-client/src/Google/Http/REST.php on line 79
• The calendar API is ON
• I used the Service Accounts credentials
• I removed all referrers
Here is the code :
<?php
session_start();
$path = 'google-api-php-client/src/';
$oldPath = set_include_path(get_include_path() . PATH_SEPARATOR . $path);
require_once 'Google/Client.php';
require_once 'Google/Service/Calendar.php';
define('SERVICE_ACCOUNT_NAME', 'XXXXXX-50dv2bprcmuhn6tuicavg2oqc3c692ua#developer.gserviceaccount.com');
/* THE PATH TO THE SECRET KEY GENERATED WHEN YOU REQUESTED THE
* SERVICE ACCOUNT. The key's name contains it's public key
* fingerprint, represented below by the string <longhexstring>
*/
define('KEY_FILE', 'XXXXXXXXXXXXXX.p12');
$client = new Google_Client();
$client->setApplicationName("My TEST Application");
/* Note: make sure to call $client->setUseObjects(true) if you want to see
* objects returned instead of data (this example code uses objects)
*/
/* If you already have a session token, use it. Normally this token is
* stored in a database and you'd need to retrieve it from there. For
* this demo we'll simply start a new session each time.
*/
session_start();
if (isset($_SESSION['token'])) {
$client->setAccessToken($_SESSION['token']);
}
/* Load the key in PKCS 12 format - remember: this is the file you had to
* download when you created the Service account on the API console.
*/
$key = file_get_contents(KEY_FILE);
$client->setAssertionCredentials(new Google_Auth_AssertionCredentials(
SERVICE_ACCOUNT_NAME,
array('https://www.googleapis.com/auth/calendar'),
$key)
);
if (isset($_SESSION['token'])) {
$client->setAccessToken($_SESSION['token']);
}
/* ------------------------- We are now properly authenticated ------------------- */
$cal = new Google_Service_Calendar($client);
$event = new Google_Service_Calendar_Event();
$event->setSummary('Dinner at Henks house');
/* what to do, summary of the appointment */
$event->setLocation('Slochteren'); /* yes, it exists */
/* Now, set the start date/time
*/
$start = new Google_Service_Calendar_EventDateTime();
$start->setDateTime('2014-08-10T19:00:00.000+01:00'); /* Or e.g. 2010-08-26T10:40:00+02:00 */
$event->setStart($start);
/* Now, set the end date/time
*/
$end = new Google_Service_Calendar_EventDateTime();
$end->setDateTime('2014-08-10T22:00:00.000+01:00'); /* 2010-08-26T10:40:00+02:00 */
$event->setEnd($end);
/* For now I just set one attendee, but you can create lists of many if you want to
*/
$attendee1 = new Google_Service_Calendar_EventAttendee();
$attendee1->setEmail('test#gmail.com');
$attendees = array($attendee1);
$event->attendees = $attendees;
/* CREATE THE EVENT IN THE PROPER CALENDAR
*/
$createdEvent = $cal->events- >insert('XXXXXXXXXXXgpl4651co#group.calendar.google.com', $event);
print "<html><body>";
echo "<pre>I created a calendar entry, it's id is '" . $createdEvent->id . "'</pre>";
print "</body></html>";
/* Here should be some code to store the token in the database again.
* Just to reminds us we put some useless code here ;-P
*/
if ($client->getAccessToken()) {
$_SESSION['token'] = $client->getAccessToken();
}
?>
I've been searching and testing for hours but nothing works fine :(
Thanks for your help

Even though the calendar is public, that does not mean anyone can write into it. For that you will either need to:
Share this public calendar with your service account.
Create an event on the service account's calendar and invite the public calendar.
Or if the calendar is domain owned you can set up your service account to be a friend of the domain (https://developers.google.com/drive/web/delegation).

I authorised the Service Accounts client_id in the Admin console of Google Apps and also deleted from the API Console the IPs in Referees tab. It worked for me. Hope it will helps

Related

PHP - Need help completing Google Sheets API request

What I'm aiming to do ~
Write to google sheets via .php file that receives html form data.
So far ~
Completed the PHP quick start here: https://developers.google.com/sheets/api/quickstart/php
Completed successfully and was able to read/write to sheet using their example.
Next I used the sample code to append a sheet, found at:
https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets.values/append
But it seems to be missing a vital piece of code. See below.
Linux Server, PHP5.
<?php
/*
* BEFORE RUNNING:
* ---------------
* 1. If not already done, enable the Google Sheets API
* and check the quota for your project at
* https://console.developers.google.com/apis/api/sheets
* 2. Install the PHP client library with Composer. Check installation
* instructions at https://github.com/google/google-api-php-client.
*/
// Autoload Composer.
require_once __DIR__ . '/vendor/autoload.php';
$client = getClient();
$service = new Google_Service_Sheets($client);
// The ID of the spreadsheet to update.
$spreadsheetId = 'my-spreadsheet-id'; // TODO: Update placeholder value.
// The A1 notation of a range to search for a logical table of data.
// Values will be appended after the last row of the table.
$range = 'my-range'; // TODO: Update placeholder value.
// TODO: Assign values to desired properties of `requestBody`:
$requestBody = new Google_Service_Sheets_ValueRange();
$response = $service->spreadsheets_values->append($spreadsheetId, $range, $requestBody);
// TODO: Change code below to process the `response` object:
echo '<pre>', var_export($response, true), '</pre>', "\n";
function getClient() {
// TODO: Change placeholder below to generate authentication credentials. See
// https://developers.google.com/sheets/quickstart/php#step_3_set_up_the_sample
//
// Authorize using one of the following scopes:
// 'https://www.googleapis.com/auth/drive'
// 'https://www.googleapis.com/auth/drive.file'
// 'https://www.googleapis.com/auth/spreadsheets'
return null;
}
?>
I would have expected to see the function 'getClient()' filled. What exactly do I need to add here?
I assume once this is filled i can just save to a php file and call to append, since my site already has authorization.
Thanks in advance.
Yasiru - Thanks for the suggestion. I now have the following ~
<?php
/*
* BEFORE RUNNING:
* ---------------
* 1. If not already done, enable the Google Sheets API
* and check the quota for your project at
* https://console.developers.google.com/apis/api/sheets
* 2. Install the PHP client library with Composer. Check installation
* instructions at https://github.com/google/google-api-php-client.
*/
// Autoload Composer.
require_once __DIR__ . '/vendor/autoload.php';
$client = getClient();
$service = new Google_Service_Sheets($client);
// The ID of the spreadsheet to update.
$spreadsheetId = 'XXXX'; // TODO: Update placeholder value.
// The A1 notation of a range to search for a logical table of data.
// Values will be appended after the last row of the table.
$range = 'Sheet1'; // TODO: Update placeholder value.
// TODO: Assign values to desired properties of `requestBody`:
//$requestBody = new Google_Service_Sheets_ValueRange();
$requestBody = {
"majorDimension": 'ROWS',
"values": [
"val1","val2"
]
}
$response = $service->spreadsheets_values->append($spreadsheetId, $range, $requestBody);
// TODO: Change code below to process the `response` object:
echo '<pre>', var_export($response, true), '</pre>', "\n";
function getClient()
{
$client = new Google_Client();
$client->setApplicationName('Google Sheets API PHP Quickstart');
$client->setScopes('https://www.googleapis.com/auth/spreadsheets');
$client->setAuthConfig('credentials.json');
$client->setAccessType('offline');
$client->setPrompt('select_account consent');
// Load previously authorized token from a file, if it exists.
// The file token.json stores the user's access and refresh tokens, and is
// created automatically when the authorization flow completes for the first
// time.
$tokenPath = 'token.json';
if (file_exists($tokenPath)) {
$accessToken = json_decode(file_get_contents($tokenPath), true);
$client->setAccessToken($accessToken);
}
// If there is no previous token or it's expired.
if ($client->isAccessTokenExpired()) {
// Refresh the token if possible, else fetch a new one.
if ($client->getRefreshToken()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
} else {
// Request authorization from the user.
$authUrl = $client->createAuthUrl();
printf("Open the following link in your browser:\n%s\n", $authUrl);
print 'Enter verification code: ';
$authCode = trim(fgets(STDIN));
// Exchange authorization code for an access token.
$accessToken = $client->fetchAccessTokenWithAuthCode($authCode);
$client->setAccessToken($accessToken);
// Check to see if there was an error.
if (array_key_exists('error', $accessToken)) {
throw new Exception(join(', ', $accessToken));
}
}
// Save the token to a file.
if (!file_exists(dirname($tokenPath))) {
mkdir(dirname($tokenPath), 0700, true);
}
file_put_contents($tokenPath, json_encode($client->getAccessToken()));
}
return $client;
}
?>
However when I load the page, I get an internal server error 500.
To clarify, the above PHP is saved in test.php and is called via url, and is located in the working directory.
Im guessing your trying to display data from your sheet not the clients.
For that you don't need the client to log in, he does not even have to know the data is coming from google sheets (obviously unless your website says that).
Best and most secure way is to do it all server side.
Unfortunately google is not very good with their documentation.
This is what worked for me:
Install the google api (best through composer).
Get "Service account keys" from https://console.developers.google.com/, and save on your server as a json file. This is the password that will allow your server to access your sheets. (Make sure the google api is enabled in your project).
In the spreadsheet that you want to access, give edit permission to the email that came with your "Service account keys".
Than use the following code:
require_once __DIR__ . '/vendor/autoload.php'; //Path to google sheets library
$client = new \Google_Client();
$client->setApplicationName('YOURAPPNAME'); //Add a name to your project. Can be any name
$client->setScopes([\Google_Service_Sheets::SPREADSHEETS]);
$client->setAccessType('offline');
$client->setAuthConfig(__DIR__ . '/****.json');// Path to the json file with the "Service account keys"
$service = new Google_Service_Sheets($client);
$spreadsheetId = "****"; // Add your spreadsheet id. Can e found in the url of your sheet.
$range = '****'; // Name of the sheet you are working with
From here you will add values to your shet
Change it based on your needs.
$valueRange= new Google_Service_Sheets_ValueRange();
$valueRange->setValues(["values" => ['Value1', 'Value2']]); //The values you will bee adding
$conf = ["valueInputOption" => "RAW"];
$ins = ["insertDataOption" => "INSERT_ROWS"];
$service->spreadsheets_values->append($spreadsheetId, $range, $valueRange, $conf, $ins);
Let me know if it works or if you still need help.
Copy the getClient() function from sample page and change the following line
$client->setScopes(Google_Service_Sheets::SPREADSHEETS_READONLY);
To
$client->setScopes('https://www.googleapis.com/auth/spreadsheets');
Or one of following
'https://www.googleapis.com/auth/drive'
'https://www.googleapis.com/auth/drive.file'

google-api-php-client connect with key.p12

I'm able to add event to my google calendar with an API keys and OAuth 2.0 client IDs but I want to do this without the authorization screen of google.
I followed the information found on this post:
stackoverflow.com/questions/8995451/how-do-i-connect-to-the-google-calendar-api-without-the-oauth-authentication
For this, I created a 'Service account keys'. I went to my project credentials and select 'Create Credentials > Service Account Key'
Then:
service account > my_project_name
Key type > p12
I saved the key file key.p12
Here is my code:
<?php
// display error, debbug
ini_set('display_errors',1);
session_start();
require_once './google-api-php-client/src/Google_Client.php';
require_once './google-api-php-client/src/contrib/Google_CalendarService.php';
// following values are taken from : console.developers.google.com/apis/credentials?project=projectname credentials
// OAuth 2.0 client IDs : Client ID
const CLIENT_ID = 'xxxx';
// Service account keys : Service account
const SERVICE_ACCOUNT_NAME = 'my_project_name';
// key
const KEY_FILE = './key.p12';
$client = new Google_Client();
$client->setApplicationName("Google Calendar API Quickstart");
if (isset($_SESSION['token'])) {
$client->setAccessToken($_SESSION['token']);
}
// Load the key in PKCS 12 format
$key = file_get_contents(KEY_FILE);
$client->setAssertionCredentials(new Google_AssertionCredentials(
SERVICE_ACCOUNT_NAME,
array('https://www.googleapis.com/auth/calendar'),
$key)
);
$client->setClientId(CLIENT_ID);
$cal = new Google_CalendarService($client);
//Save token in session
if ($client->getAccessToken()) {
$_SESSION['token'] = $client->getAccessToken();
}
// my code here
$event = new Google_Event(...
$calendarId = 'mycalendarID#group.calendar.google.com';
$event = $cal->events->insert($calendarId, $event);
?>
And here is the error message:
Fatal error: Uncaught Google_AuthException: Error refreshing the OAuth2 token, message: '{
'error' : 'invalid_client',
'error_description' : 'The OAuth client was not found.'
}' in /home/www/google-api-php-client/src/auth/Google_OAuth2.php:288
Stack trace:
#0 /home/www/google-api-php-client/src/auth/Google_OAuth2.php(264): Google_OAuth2->refreshTokenRequest(Array)
#1 /home/www/google-api-php-client/src/auth/Google_OAuth2.php(218): Google_OAuth2->refreshTokenWithAssertion()
#2 /home/www/google-api-php-client/src/service/Google_ServiceResource.php(167): Google_OAuth2->sign(Object(Google_HttpRequest))
#3 /home/www/google-api-php-client/src/contrib/Google_CalendarService.php(469): Google_ServiceResource->__call('insert', Array)
#4 /home/www/goog in /home/www/google-api-php-client/src/auth/Google_OAuth2.php on line 288
It seems that the $client->getAccessToken() isn't set but I don't know why.
Thanks in advance for your help.
Create service account key and download the *.json file that contains private keys. Put the *.json file you just downloaded in a directory of your choosing ( credentials.json file in the example ). Then go to Google Calendar->Share and add service account id on the list.
putenv( 'GOOGLE_APPLICATION_CREDENTIALS=credentials.json' );
$client = new Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope( 'https://www.googleapis.com/auth/calendar' );
$client->setHttpClient( new GuzzleHttp\Client( [ 'verify' => false ] ) ); // disable ssl if necessary
$service = new Google_Service_Calendar( $client );
// list events
$service->events->listEvents( $calendar_id, array( 'timeMin' => ( new DateTime )->format( DateTime::RFC3339 ) ) );
// add event
$event = new Google_Service_Calendar_Event( $data );
$event = $service->events->insert( $calendar_id, $event );
You can find the Google APIs PHP Client Library package with autoloader in the releases page on GitHub, so the only require_once call necessary is for autoload file:
require_once '/path/to/google-api-php-client/vendor/autoload.php';
And, Google docs may help you further, this is just one way that works for me so it may be useful to you as well.

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 Admin SDK PHP cannot create user. Not Authorized

I'm having a problem implementing Google Admin SDK in PHP. It always give error
Fatal error: Uncaught exception 'Google_Service_Exception' with message 'Error calling POST
https://www.googleapis.com/admin/directory/v1/users: (403) Not Authorized to access this
resource/api' in ..\google-api-php-client\src\Google\Http\REST.php on line 79
Here is my code :
<?php
session_start();
/* * **********************************************
Make an API request authenticated with a service
account.
* ********************************************** */
set_include_path("google-api-php-client/src" . PATH_SEPARATOR . get_include_path());
require_once 'Google/Client.php';
require_once 'Google/Service/Directory.php';
/* * **********************************************
ATTENTION: Fill in these values! You can get
them by creating a new Service Account in the
API console. Be sure to store the key file
somewhere you can get to it - though in real
operations you'd want to make sure it wasn't
accessible from the webserver!
The name is the email address value provided
as part of the service account (not your
address!)
Make sure the Books API is enabled on this
account as well, or the call will fail.
* ********************************************** */
$client_id = 'my_client_id'; //Client ID
$service_account_name = 'email'; //Email Address
$key_file_location = 'key.p12'; //key.p12
if ($client_id == '<YOUR_CLIENT_ID>' || !strlen($service_account_name) || !strlen($key_file_location)) {
echo missingServiceAccountDetailsWarning();
}
$client = new Google_Client();
$client->setApplicationName("appname");
$service = new Google_Service_Directory($client);
/* * **********************************************
If we have an access token, we can carry on.
Otherwise, we'll get one with the help of an
assertion credential. In other examples the list
of scopes was managed by the Client, but here
we have to list them manually. We also supply
the service account
* ********************************************** */
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/admin.directory.user'), $key
);
$client->setAssertionCredentials($cred);
if ($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion($cred);
}
$_SESSION['service_token'] = $client->getAccessToken();
/* * **********************************************
We're just going to make the same call as in the
simple query as an example.
* ********************************************** */
$familyName = filter_input(INPUT_GET, 'familyname');
$givenName = filter_input(INPUT_GET, 'givenname');
$password = filter_input(INPUT_GET, 'password');
$primaryEmail = filter_input(INPUT_GET, 'email');
$user = new Google_Service_Directory_User();
$name = new Google_Service_Directory_UserName();
$name->setFamilyName($familyName);
$name->setGivenName($givenName);
$user->setName($name);
$user->setHashFunction("MD5");
$user->setPrimaryEmail($primaryEmail);
$user->setPassword(hash("md5", $password));
$result = $service->users->insert($user);
There is no documentation and I'm very confused with this error.
I had a similar problem until I set the "sub" account on the credentials object which is the email address for the administrative user that you want to perform the API action as.
So in Google Apps Admin for your domain I assume you've created a user and added them to and admin role that has API access to users right? In your code above you just need to add (with correct email address of course):
$cred->sub = "adminuser#domain.com";
Add that right before:
$client->setAssertionCredentials($cred);
I did a full example for someone else that you might be able to reference too: https://gist.github.com/fillup/9fbf5ff35b337b27762a
I had a similar problem but found a solution to this by going through this blog
http://michaelseiler.net/2014/12/16/google-admin-sdk-api-with-php/
Assuming you have done all the necessary setting up on the Admin Console (i.e. delegating domain authority), then pay particular attention to the line
`$cred = new Google_Auth_AssertionCredentials($service_account_name, array('https://www.googleapis.com/auth/admin.directory.user'), $key);`
this should be:
`$user_to_impersonate = 'adminaccount#example.com';$scopes =array('https://www.googleapis.com/auth/admin.directory.user');$cred = new Google_Auth_AssertionCredentials(
$service_account_name,
$scopes,
$key,
'notasecret', // Default P12 password
'http://oauth.net/grant_type/jwt/1.0/bearer', // Default grant type
$user_to_impersonate);`
I changed that and boom....
I think i was receiving this error when i tried to query a user.
During the creation of the JWT_CLAIM portion of the assertion, you must specify a domain admin account that your service account can impersonate... this part was poorly documented, i thought.
i dont know exactly how the google php library does it, but i didnt see anywhere in your code where you specify that account email address. if you have looked at the oauth2 documentation, in the jwt_claim secion, there is an "additional claims" subsection that says:
To obtain an access token that grants an application delegated access to a resource, include the email address of the user in the JWT claim set as the value of the sub field.
I had to include that admin email account in the creation of my assertion before i could even query the directory.users API.
i apologize if this isnt helpful, but im not using the library for php, im building my own (with php).

google service account authentication with google-api-php-client using calendar api

i am using php 5.3.3, and codeigniter 2.1.0.
what i want to do is set up a service account, so a user can add an appointment in a text entry field on my website, then have that appointment added to a shared shared google calendar.
i have a google account, and using : https://code.google.com/apis/console I created a new project called 'pqp'
on services: enabled the calendar api
on api access: i created an oath 2.0 client id… product name = pqp, application type = service account.
downloaded the key 46… -privatekey.p12. there is a screenshot of the settings:
I got an svn checkout of the google-api-php-client (28/6/2012)
In the google-api-php-client/src/config.php I changed lines:
25: 'application_name' => 'pqp',
28: 'oauth2_client_id' => '373xxx730.apps.googleusercontent.com',
57: 'ioFileCache_directory' => 'tmp/apiClient', // my apache user does not have access to the system /tmp folder. + tmp/apiClient has permissions of 777 on the server.
using this link:
http://code.google.com/p/google-api-php-client/source/browse/trunk/examples/prediction/serviceAccount.php?spec=svn445&r=395
I modified it to:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Test extends CI_Controller{
function __construct()
{
parent::__construct();
}
function index()
{
set_include_path(get_include_path() . PATH_SEPARATOR .dirname(__FILE__).'/../libraries/google-api-php-client/src');
ini_set('error_reporting',E_ALL);
ini_set('display_errors','1');
// Set your client id, service account name, and the path to your private key.
// For more information about obtaining these keys, visit:
// https://developers.google.com/console/help/#service_accounts
define('CLIENT_ID','3731xxx44730.apps.googleusercontent.com');
define('SERVICE_ACCOUNT_NAME','373xxx244730#developer.gserviceaccount.com');
// Make sure you keep your key.p12 file in a secure location, and isn't
// readable by others.
define('KEY_FILE',dirname(__FILE__).'/../../461290xxx796c0b7db9582c-privatekey.p12');
require_once "apiClient.php";
require_once "contrib/apiCalendarService.php";
$client = new apiClient();
$client->setApplicationName("pqp");
// Set your cached access token. Remember to replace $_SESSION with a
// real database or memcached.
session_start();
if (isset($_SESSION['token'])) {
$client->setAccessToken($_SESSION['token']);
echo 'client access token is set.<br/>';
}
// 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);
$creds = new apiAssertionCredentials(SERVICE_ACCOUNT_NAME,array('https://www.googleapis.com/auth/calendar'),$key);
$client->setAssertionCredentials($creds);
$client->setClientId(CLIENT_ID);
$service = new apiCalendarService($client);
echo 'client:<br/>';
var_dump($client);
echo 'service:<br/>';
var_dump($service);
// We're not done yet. Remember to update the cached access token.
// Remember to replace $_SESSION with a real database or memcached.
if ($client->getAccessToken()) {
$_SESSION['token'] = $client->getAccessToken();
echo 'token is good!, so creating an event....';
echo $this->insert_event($service,'testing summary','my location','2012-06-29T10:00:00.000+10:00','2012-06-29T10:00:00.000+10:00');
}
}
function insert_event($service,$summary,$location,$from,$to){
$event = new Event();
$event->setSummary($summary);
$event->setLocation($location);
$start = new EventDateTime();
$start->setDateTime($from);
$event->setStart($start);
$end = new EventDateTime();
$end->setDateTime($to);
$event->setEnd($end);
$attendee1 = new EventAttendee();
$attendee1->setEmail('test#example.com');
$attendees = array($attendee1);
$event->attendees = $attendees;
$createdEvent = $service->events->insert('primary', $event);
return $createdEvent->getId();
}
}
a pastie of the output is here:
the $client object is not authenticated, the getAccessToken is not set, and the event is not inserted.
i have found it difficult to work out which settings in the $config file to change because there is different nomenclature. i guess this is an artifact of how the code has progressed.
are the settings in src/config.php correct? do i need to alter any more settings?
it is my understanding that if i create the service account, download the key file, and the contents of this file with my developer id, it should return a token, and there is no need to set up a redirection uri.. is that correct? this is the functionality i want. i don't want the user to have to authorise access because the website will only ever interact with one google account.
So, the question is, how do i get this calendar api to authenticate using a google service account?
You can try this one if you not already...
EDIT: this one intresting but if you still feel like to write one yourself then try this THE mother of the oauth2. helpful
About Service Account at google-api-php-client that you use(always take the trunk's one with SVN) I can't found in that code manipulations any reference apiAssertionCredentials::generateAssertion()
definitely there is no call to auth in there
public function __construct(
$serviceAccountName,
$scopes,
$privateKey,
$privateKeyPassword = 'notasecret',
$assertionType = 'http://oauth.net/grant_type/jwt/1.0/bearer',
$prn = false) {
$this->serviceAccountName = $serviceAccountName;
$this->scopes = is_string($scopes) ? $scopes : implode(' ', $scopes);
$this->privateKey = $privateKey;
$this->privateKeyPassword = $privateKeyPassword;
$this->assertionType = $assertionType;
$this->prn = $prn;
}
and this method should be called I guess...
public function generateAssertion() {
$now = time();
$jwtParams = array(
'aud' => apiOAuth2::OAUTH2_TOKEN_URI,
'scope' => $this->scopes,
'iat' => $now,
'exp' => $now + self::MAX_TOKEN_LIFETIME_SECS,
'iss' => $this->serviceAccountName,
);
if ($this->prn !== false) {
$jwtParams['prn'] = $this->prn;
}
return $this->makeSignedJwt($jwtParams);
}
EDIT:
Pardon. In fresh ver. look's like it's Google_OAuth2::refreshTokenWithAssertion() actualy who should start the real proces

Categories