Impersonate the user EMAIL ID using Google Oauth2 Credentials ‘Service Account’ - php

I am trying to create Google calendar events using Google Api OAuth service Account from PHP GAE.
I need the correct Session ID or the user EMail ID in the Calendar events field ‘created by’.
This is possible well in Google Apps Script(GAS), it creates the events with the correct session ID.
But, I want the same to be done in PHP GAE(Google App Engine). So, I tried to impersonate the user ID as follows:Perform Google Apps Domain-Wide Delegation of Authority
My aim is to insert the correct user ID of any end user automatically as like in GAS(Google Apps Script). I don't want any default credentials to be set in the field ‘created by’..
Using the PHP client library i tried to impersonate a user in Calendar API.I didn't get any complete sample for Calendar API.So, I tried the Drive API documentation sample, this sample seems to be working fine, Using other domain user also
Using Calendar API I wrote the below example.
<?php
require_once realpath(dirname(__FILE__).'/google-api-php-client-master/src/Google/autoload.php');
require_once realpath(dirname(__FILE__).'/google-api-php-client-master/src/Google/Service/Calendar.php');
require_once realpath(dirname(__FILE__).'/google-api-php-client-master/src/Google/Service/Oauth2.php');
use google\appengine\api\users\User;
use google\appengine\api\users\UserService;
$user = UserService::getCurrentUser();
$userEmail=$user->getEmail();
$client_email = '34234242424-qssjf8kg1kk42dnjdvd2ndrk7rou44#developer.gserviceaccount.com';
$private_key = file_get_contents('key.p12');
$scopes = array('https://www.googleapis.com/auth/calendar');
$credentials = new Google_Auth_AssertionCredentials(
$client_email,
$scopes,
$private_key
);
$credentials->sub = $userEmail;
$client = new Google_Client();
$client->setAssertionCredentials($credentials);
if ($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion();
}
$service =new Google_Service_Calendar($client);
$event = new Google_Service_Calendar_Event();
$start = new Google_Service_Calendar_EventDateTime();
$start->setDateTime('2015-09-26T10:00:00.000-07:00');
$event->setStart($start);
$end = new Google_Service_Calendar_EventDateTime();
$end->setDateTime('2015-09-26T10:00:00.000-07:00');
$event->setEnd($end);
$createdEvent = $service->events->insert('abc#group.calendar.google.com', $event);
It’s working well when i check this email, i got the correct service account credentials.
But when i used different email ID, i got this below error
PHP Fatal error: Uncaught exception 'Google_Auth_Exception' with message 'Error refreshing the OAuth2 token, message: '{ "error" : "unauthorized_client", "error_description" : "Unauthorized client or scope in request." }'' in /base/data/home/apps/s~production/1.3874/google-api-php-client-master/src/Google/Auth/OAuth2.php:363 Stack trace: #0 /base/data/home/apps/s~production/1.387/google-api-php-client-master/src/Google/Auth/OAuth2.php(314): Google_Auth_OAuth2->refreshTokenRequest(Array) #1 /base/data/home/apps/s~ei-html-production/1.3874/final.php(34): Google_Auth_OAuth2->refreshTokenWithAssertion() #2 {main} thrown in /base/data/home/apps/s~production/1.38742/google-api-php-client-master/src/Google/Auth/OAuth2.php on line 363
Plz help me what i did wrong.Why the issue happens, when I used diff email ID, my end user who'll create cal events, could be any GMAIL or Google based domain ID.
So, plz help with at least a sample part...
Reference links:
How do I Insert Google Calendar Event using Google Api 3 for any user in the domain?
How to create a Google Calendar event without a reminder / How to get Service Accounts to impersonate users

You can only impersonate users on a google apps domain where you have the necessary permission for (search for 'domain wide delegation'). You've got that covered.
Once you're authorized for impersonation you have to recreate a fresh Google Client for each user you impersonate. You'll only receive an access_token you can use for this very user. If you just change the email address once you're authorized it will not work.

Related

Auth Google Analytics PHP API

I have tried the official HelloAnalytics tutorial however it doesn't work.
I am recieveing this error:
"PHP Fatal error: Class 'Google_Auth_AssertionCredentials' not found"
My Code:
// Creates and returns the Analytics service object.
// Load the Google API PHP Client Library.
require_once 'vendor/autoload.php';
// Use the developers console and replace the values with your
// service account email, and relative location of your key file.
$service_account_email = 'xxxxxxxxxxx#gmail.com';
$key_file_location = 'key_anyl.p12';
// Create and configure a new client object.
$client = new Google_Client();
$client->setApplicationName("HelloAnalytics");
$analytics = new Google_Service_Analytics($client);
// Read the generated client_secrets.p12 key.
$key = file_get_contents($key_file_location);
$cred = new Google_Auth_AssertionCredentials(
$service_account_email,
array(Google_Service_Analytics::ANALYTICS_READONLY),
$key
);
$client->setAssertionCredentials($cred);
if($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion($cred);
}
Update:
after adding the suggested V1-master branch I am now getting the following error
Uncaught exception 'Google_Service_Exception' with message 'Error
calling GET googleapis.com/analytics/v3/management/accounts: (403)
User does not have any Google Analytics account.'
Problem nr 1:
if your not using composer make sure you downloaded the v1-master branch – Link
Problem nr 2:
(403) User does not have any Google Analytics account.
You are using a service account by default a service account does not have access to any google analytics accounts. You need to take the service account email address from Google Developers console and add it as a user at the ACCOUNT level it must be the ACCOUNT level in the Google Analytics website under the admin section.
For your problem you need to add the base directory of the library in the php 'include_path'.
Try putting this line of code before the require_once
set_include_path( get_include_path() . PATH_SEPARATOR . 'vendor/google/src' );

Get user login access token to use youtube API

I am using youtube API for scheduling live events for user in my application.
Once the user logged in my application i need to logged in the same user to our business google account(One google account for all user) without giving login credentials. and to get access token for scheduling the live events.
Is it possible to login the user into google account without giving login credentials(User will not feel he is login to another account).
Is it feasible with PHP?.Please give one example to get access token for youtube API access.
I used the following code for getting access token but service account can't access the youtube service.
My code for getting access token using service account:
<?php
require_once 'Google/autoload.php';
session_start();
$client_id = '395540674667-p64tdfqdsfsdfdsf#dsfd.com';
$Email_address = '54564-drgfdg1#developer.gserviceaccount.com';
$key_file_location = 'Youtube API-5czxczxc86.p12';
$client = new Google_Client();
$client->setApplicationName("Youtube API");
$key = file_get_contents($key_file_location);
// seproate additional scopes with a comma
$scopes = array('https://www.googleapis.com/auth/sqlservice.admin','https://www.googleapis.com/auth/plus.login','https://www.googleapis.com/auth/youtube');
$cred = new Google_Auth_AssertionCredentials($Email_address,
$scopes,
$key);
$client->setAssertionCredentials($cred);
if($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion($cred);
}
//print_r($client);
echo $client->getAccessToken();
?>
I am expecting the answer is something like this.Any one please help
you example about Youtube api, first:
select credentials to your api project from here:
https://console.cloud.google.com/home/dashboard?project= with your project
also you need to have the api enable because google told us "Some APIs are enabled automatically."
when you select:
https://console.cloud.google.com/apis/api/youtube/ with Go to Credentials you have some option into modal window this will help
also.
the php code seem to be ok but also I think you will change after you learn more about Credentials settings.

How can I insert data (event) into Google Calendar with PHP?

I am trying to insert events into Google Calendar, but I get errors everytime. I've been searching for hours to get answer, but I found nothing for my problem. I tested a lot of examples, without success. I'm new in Google Calendar, and I can't really understand the google api documentation.
I have a Fullcalendar which uses the Google Calendar (Gcal) as backend. I can read data from Gcal without any problems. When I try to displayed using Fullcalendar, but when I want to write some test datas into Gcal it gives me errors. I want to make a Calendar application which serves as a reservation app. So I have a Calendar, which is displayed to everyone who enter the page, and they can reserve appointments, which are stored in my Google Calendar.
The main is problem is that, I don't really know how to make the connection to Google Calendar for writing data. Every sample I've seen, solves the problem different way, major of them are outdated, some of them uses Sessions, but I don't need Session because the Calendar I want to display is FIX, everyone sees the same.
The code:
require_once 'Google/src/Google/autoload.php';
require_once "Google/src/Google/Client.php";
require_once "Google/src/Google/Service/Calendar.php";
$client_id = 'XXXXXXXXXX-f9ltk86b2klat20k1osmfbgpu4u1vqse.apps.googleusercontent.com';
$client_secret = 'XXXXXXXXXXXXXXXXXXXXXXX';
$key = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'; // Server Key
$email_address = 'XXXXXXXXXXXX-f9ltk86b2klat20k1osmfbgpu4u1vqse#developer.gserviceaccount.com';
$client = new Google_Client();
$client->setApplicationName("Calendar");
$client->setClientId($client_id);
$client->setClientSecret($client_secret);
$client->setDeveloperKey($key);
$client->setScopes(array(
'https://www.googleapis.com/auth/plus.login',
));
$cal = new Google_Service_Calendar($client);
$event = new Google_Service_Calendar_Event();
$event->setSummary('Title');
$event->setDescription('Title');
$event->setLocation('Somewhere');
$start = new Google_Service_Calendar_EventDateTime();
$start->setDateTime('2013-08-17T16:00:00.000-07:00');
$event->setStart($start);
$end = new Google_Service_Calendar_EventDateTime();
$end->setDateTime('2013-08-17T17:00:00.000-07:00');
$event->setEnd($end);
$createdEvent = $cal->events->insert('<Calendar ID>', $event);
The exception it generates:
[19-Jun-2015 09:08:59 Europe/Berlin] PHP Fatal error: Uncaught exception 'Google_Service_Exception' with message 'Error calling POST
https://www.googleapis.com/calendar/v3/calendars/hpba8d7p1f6l65ruhbl9qigvks%40group.calendar.google.com/events?key=XXXXXXXXXXXXXXXXXXXXXXXXXXXXX:
(401) Login Required' in
/var/www/XXXXXXXXXXXXXXXXXXXX/calendar/Google/src/Google/Http/REST.php:110
Login Required means that you have not authenticated properly.
By looking at the scope you are using I think that might give you a hint as to why its not working
'https://www.googleapis.com/auth/plus.login'
You are passing the scope for Google+ you should be passing one of the Google calendars scopes if you want to access Google calendar data.
https://www.googleapis.com/auth/calendar read/write access to Calendars
https://www.googleapis.com/auth/calendar.readonly read-only access to Calendars
Authenticate with a service account
<?php
require_once 'Google/autoload.php';
session_start();
/************************************************
The following 3 values an befound in the setting
for the application you created on Google
Developers console. Developers console.
The Key file should be placed in a location
that is not accessable from the web. outside of
web root.
In order to access your GA account you must
Add the Email address as a user at the
ACCOUNT Level in the GA admin.
************************************************/
$client_id = '[your client]';
$Email_address = '[your service account email]';
$key_file_location = '[Your key]';
$client = new Google_Client();
$client->setApplicationName("Client_Library_Examples");
$key = file_get_contents($key_file_location);
// separate additional scopes with a comma
$scopes ="https://www.googleapis.com/auth/calendar";
$cred = new Google_Auth_AssertionCredentials(
$Email_address,
array($scopes),
$key
);
$client->setAssertionCredentials($cred);
if($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion($cred);
}
$service = new Google_Service_Calendar($client);
?>
code ripped from tutorial PHP Google Calendar service account
Tip: make sure that you have given the service account access to the calendar in question. You just need to add the service account email to the calendar like you would any other user.

AdSense Management API - Missing required parameter: redirect_uri With Service Account

I am getting the following Error when trying to connect with the AdSense Management API Example:
Missing required parameter: redirect_uri
I am using a service Account, because my Server handles all the interaction between the adSense api. The user is not involved. Here is my PHP Code:
$client = new Google_Client();
$client->setApplicationName("PeopleHelpingPeople"); // name of your app
// set assertion credentials
$client->setAssertionCredentials(
new Google_Auth_AssertionCredentials(
"...",
array('https://www.googleapis.com/auth/analytics.readonly'),
file_get_contents('client_data.json') // keyfile you downloaded
));
$client->setScopes(array(
'https://www.googleapis.com/auth/analytics.readonly'
));
$client->setClientId("..."); // from API console
$client->setAccessType('offline_access'); // this may be unnecessary?
// Create service.
$service = new Google_Service_AdSense($client);
Why am I getting this Error?
If you are trying to use a ServiceAccount from the developers console, the kind of account that gives you a p12 file, those will not work with Adsense.
Take a look at the note on this page https://developers.google.com/adsense/management/getting_started
$client->setRedirectUri() may get you past this error but it wont solve your ultimate issue

Fetch Google Calendar Events on PHP server after authenticating on iOS app

Okay so here's what I want to do...
user authorized the app on iPhone with read/write access to Google calendar
I get an auth token of some kind from Google
Pass on the token to my PHP server and save it in database
Use the token to regularly check on Google events and store them in server's database
Send the Google events data as json to the app
I want to implement the fetching of Google events on server, so that I can build additional functionality around them like sending remote push notifications.
I am stuck at the part of getting auth token and saving it on server and using it to fetch events from Google's calendar api, having not able to find the resources for same. Can somebody throw some light on this.
UPDATE
I have been able to successfully implement the scenario till step 3.
I get the auth token and refresh token from Google and save it in database. Now using the Google API php client, I am trying to connect to Google's calendar API using the access token that I got earlier. I am using the following code...
require_once(APPPATH . "libraries/Google/Google_Client.php");
require_once(APPPATH . "libraries/Google/contrib/Google_CalendarService.php");
$client = new Google_Client();
$client->setAccessToken($google_access_token);
$calendar = new Google_CalendarService($client);
$calendarList = $calendar->calendarList->listCalendarList();
echo print_r($calendarList, true);
But now I get this error...
PHP Fatal error: Uncaught exception 'Google_AuthException' with
message 'Could not json decode the token' in
/myserver/application/libraries/Google/auth/Google_OAuth2.php:162
Stack trace:
/myserver/application/libraries/Google/Google_Client.php(170): Google_OAuth2->setAccessToken('a_token...')
I understand that I am directly trying to set the access token in Google client api without specifying any redirect url or other params normally used when the user authorizes the access to Google calendars on server itself. Is this supposed to work like I am trying to?
UPDATE 2
Upon some further digging, I found out that directly setting the access token using setAccessToken does not work as Google client for API expects a JSON encoded string in the setAccessToken method. After some tweaks I changed my code to following....
require_once(APPPATH . "libraries/Google/Google_Client.php");
require_once(APPPATH . "libraries/Google/contrib/Google_CalendarService.php");
$client = new Google_Client();
$client->setAccessType('offline');
$client->refreshToken($google_refresh_token);
$newToken = $client->getAccessToken();
$client->setAccessToken($newToken);
$calendar = new Google_CalendarService($client);
$calendarList = $calendar->calendarList->listCalendarList();
echo print_r($calendarList, true);
Now the error that I am getting is that of an invalid_request.
Error refreshing the OAuth2 token, message: '{"error" : "invalid_request"}'
Finally I am able to answer my own question. Hope this helps someone else.
Step 1 & 2. I got the Google OAuth protocol working in my iOS App following the instructions in this excellent tutorial on mobiletuts.
Step 3. I saved the access token and refresh token in database on my web server.
Step 4. Using the refresh token I got from iOS App I connected to the Google calendar API with this code...
require_once(APPPATH . "libraries/Google/Google_Client.php");
require_once(APPPATH . "libraries/Google/contrib/Google_CalendarService.php");
/* setup google client object */
$client = new Google_Client();
$client->setClientId(GOOGLE_CLIENT_ID);
/* refresh access token */
$client->refreshToken($google_refresh_token);
$newToken = $client->getAccessToken();
$client->setAccessToken($newToken);
/* get google calendars list */
$calendar = new Google_CalendarService($client);
$calendarList = $calendar->calendarList->listCalendarList();
echo print_r($calendarList, true);

Categories