Accessing calendars from service account

21,305 views
Skip to first unread message

Daniel Fischer

unread,
Nov 5, 2012, 11:59:53 AM11/5/12
to google-ca...@googlegroups.com

I believe I am successfully authorizing a service account and I can make calls to the google calendar api using this service account without errors, but when I try to list the calendars that are associated with the service account it isn't returning any calendars. I thought it would return the same as my personal company email (the email i used to create the service account). If I put in the calendarId I receive a "Google::APIClient::ClientError? (Not Found)". I used this same calendarId successfully while doing a web based authorization with my personal company email.

Is there anything special I have to do to make it so the service account sees the same calendars as my personal company email? Do I need to manually add the service account email to those calendars or something? 

Thanks for the help, 

Dan

Daniel Fischer

unread,
Nov 5, 2012, 8:23:42 PM11/5/12
to google-ca...@googlegroups.com
I just had our account admin share the calendars with my service account's email address and that worked.

Fortean

unread,
Nov 9, 2012, 5:04:55 AM11/9/12
to google-ca...@googlegroups.com
Hi, Daniel.

I have been playing a bit with the calendar API myself, using the PHP libs and service mode. Had the same experience you had. It took me te best part of two hours to figure out what the problem was.  A 'read me first' might be handy and it should contain a section on this.  Also, some decent documentation on how to use the client libs (PHP) would not be bad eithe. I haven't found it yet, have you?.

Anyway, next hurdle: I want to insert an event into my calendar, but haven't figured out how to.

What I do is: acquiring a valid token (service mode), then set up a new event opbject, fill in some handy details like start- and end dates, attendees etc. and then call $service->events->insert('MY_CALENDAR_ID', $event). where MY_CALENDAR_ID is the account name for my personal calender (which I share with my developers account).

No cigar, just anhother nasty error message "PHP Fatal error:  Uncaught exception 'Google_ServiceException' with message 'Error calling POST https://www.googleapis.com/calendar/v3/calendars/<MY_CALENDAR_ID>/events: (400) Bad Request' in .google-api-php-client/src/io/Google_REST.php:66

Daniel Fischer

unread,
Nov 9, 2012, 11:32:36 AM11/9/12
to google-ca...@googlegroups.com
Sorry I can't be much help as I was just reading events, not inserting or updating them.  Make sure your start and end dates and all the parameters are in the correct format. I think I was getting that error when my parameters were incorrect for timeMin and timeMax. 


--
You received this message because you are subscribed to the Google Groups "Google Calendar API" group.
To view this discussion on the web visit https://groups.google.com/d/msg/google-calendar-api/-/tsErJgsHh0wJ.

To post to this group, send email to google-ca...@googlegroups.com.
To unsubscribe from this group, send email to google-calendar...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/google-calendar-api?hl=en.

Fortean

unread,
Nov 9, 2012, 11:59:47 AM11/9/12
to google-ca...@googlegroups.com
To my horror I found some documentation that says that the calendar API does not work with service mode: https://code.google.com/p/google-api-php-client/wiki/OAuth2

It says:

Warning: Very few Google APIs currently support Service Accounts. Service accounts are currently supported by the following Google developer services:

  • Google Cloud Storage
  • Google Prediction API
  • Google URL Shortener
  • Google OAuth 2.0 Authorization Server
  • Google BigQuery

.. nothing about calendar..

So, anyone in here who got it working? Daniel, you seem to be able to read calendar events - I assume you can read events form a set of calendars that have been configured to be shared with your developers calendar - does it work?


(Not much use of starting a cruisade when there is no Jerusalem ;-p)..


Daniel Fischer

unread,
Nov 9, 2012, 12:21:25 PM11/9/12
to google-calendar-api
Yes, I saw that as well. I think that is old. I've successfully used the google calendar api to list out calendars and events using a service account. Have you gone to you calendar settings and shared it with your service email? Then just try listing out the calendars to make sure its working. I dont think you need to add any parameters for this, so it should eliminate any formatting problems. 

I was using the ruby client to list the calendars like this:
    calendar = client.discovered_api('calendar', 'v3')
    result = client.execute!(:api_method => calendar.calendar_list.list)
    result.data   will show the calendars

so i guess for php based on your code it would be something like this:
$service->calendar_list->list

I hope that helps.




--
You received this message because you are subscribed to the Google Groups "Google Calendar API" group.

Fortean

unread,
Nov 9, 2012, 4:32:02 PM11/9/12
to google-ca...@googlegroups.com
Hi, Daniel,

yes, I have a working small PHP program that can list the calendars, see the code snippet I have included. This correctly lists both calendars I want to access: the developers calendar and  my own calendar (which I have configured to be shared with my 'developer').


so i guess for php based on your code it would be something like this:
$service->calendar_list->list

This is a snippet of the code I use to do about the same. This ia of course after I have authentiated using client->setAssertionCredentials(new Google_AssertionCredentials(SERVICE_ACCOUNT_NAME,  array('https://www.googleapis.com/auth/calendar'),   $key));


$cal = new Google_CalendarService($client);
$calendarList = $cal->calendarList->listCalendarList();


print "<html><body>";
print "<h1>Calendar List</h1><pre>";
while(true) {
  foreach ($calendarList->getItems() as $calendarListEntry) {
    echo $calendarListEntry->getSummary() . " (";
    echo $calendarListEntry->getAccessRole() . ")<BR>";
  }

  /* Any next page? Get it. If not, we're done
   */
  $pageToken = $calendarList->getNextPageToken();
  if ($pageToken) {
    $optParams = array('pageToken' => $pageToken);
    $calendarList = $service->calendarList->listCalendarList($optParams);
  } else {
    break;
  }
}
print "</pre>";
print "</body></html>";
 
As said, when I run this both calendars are listed, so it seems to work in the more general sense. However, when I try to update my calendar, it bummers.

Anybody in here who got it working?

Thre is also some confusion on how you have to select the calendar you'd like to modify. From what I have read so far you should actuall use another form of the call to the authentication method, e.g. like this:

$prn = 'mycal...@google.com'; /* replace with your real calendar name */;
$scopes = array('https://wwww.googleapis.com/auth/calendar');
$client->setAssertionCredentials(new Google_AssertionCredentials(
        CLIENT_ID,
        $scopes,
        $key,
        'notasecret',
        'http://oauth.net/grant_type/jwt/1.0/bearer',
        $prn));

.. but I'm not sure. Anybody in here who knows?

Chet

unread,
Nov 9, 2012, 4:51:53 PM11/9/12
to google-ca...@googlegroups.com

I do it in python by setting the calendar owner's email address in prn.



On Monday, November 5, 2012 11:59:53 AM UTC-5, Daniel Fischer wrote:

Daniel Fischer

unread,
Nov 9, 2012, 4:53:09 PM11/9/12
to google-ca...@googlegroups.com
I don't think you need to set the prn parameter to anything because you have shared the calendar already with your service account and are able to return a list of calendars it has access to. You do not set the calendar you want to modify within the authorization section, because you say you already have access to the calendar. You send it as the calendarId within the api request. The calendar id can be found within the data returned in the calendar list or you can look in your calendar settings and calendar details to find the calendar id. 

Sorry its ruby but I'm assuming the parameters are the same and that seems to be where you're messing up.
Assuming the calendar is being returned in the calendar list you should be able to access its events like this.

result = client.execute!(:api_method => calendar.events.list, :parameters => {'calendarId' => calendar_id_that_returned})

so probably something like $service->events->list($calendarListEntry->getId())


--
You received this message because you are subscribed to the Google Groups "Google Calendar API" group.

Fortean

unread,
Nov 10, 2012, 7:46:40 AM11/10/12
to google-ca...@googlegroups.com


On Friday, November 9, 2012 10:53:12 PM UTC+1, Daniel Fischer wrote:
I don't think you need to set the prn parameter to anything because you have shared the calendar already with your service account 

Confirmed. Alas, I had to resolve to digging into the PHP source code, but indeed, you do not need to set the PM calendar. You have to provide the calendar id in the call to the methods that list, update, delete or inserts events.  I'm currently hacking away to see if I can some code that actually works. For now, I have been able to succesfully list EVENTS (not calendars, but EVENTS) from the calendars whose id - indeed - I could list with the code I already included. If I have something that works, I will publish it in here. Also, I am considering writing something like a "Quick Start Guide" for PHP folks as I can imagine there is a need for it >-/..

Will report back. Thanks for all the input, folks, we'll get there eventually.

Fortean

unread,
Nov 10, 2012, 1:33:55 PM11/10/12
to google-ca...@googlegroups.com
<?php
/*
Say you have some kind of PHP based web application that needs to set appoint-
ments in (various) Google calendars. How do you do this?

There are some steps to take. Here they are:

a) Log in into the Google account you want to use to manage your projects.

b) Go to https://code.google.com/apis/console/

c) Create a project. You will get issued a project number, in our example
   we'll use 99999999999.

d) Allow the project to use the calendar API:
   -> services (left pane), then find 'calendar api' and set the button 'on'

e) Create a Service Account.
   -> API access (left pane); select 'create service account'
   Part of the procedure is that you'll get a PKCS#12 bundle, which you can
   download and should store on your appserver in a secure location. Your
   app should be able to access it, but outsiders should not be allowed to
   download it.

f) download and install the Google PHP libraries.
   Google says "The mechanics of the interaction between Google and your
   application require applications to create and cryptographically sign JSON Web
   Tokens (JWTs). Developers are strongly encouraged to use a library to perform
   these tasks. Writing this code without the use of a library that abstracts
   token creation and signing is prone to errors that can have a severe impact
   on the security of your application."

   The PHP libs can be found here:
   https://code.google.com/p/google-api-php-client/wiki/OAuth2

g) to enable your application to get access to other folks calendars (or to
   your own, for that matter), the owner of that calendar (somebody that has
   the role 'owner' there) has to allow your system account's 'client id' to
   access his calendar. If you want to be able to have your system make an
   appointment, it needs at least write rights.
   See: http://support.google.com/a/bin/answer.py?hl=en&answer=162106

** Read more about service accounts here:
   https://developers.google.com/accounts/docs/OAuth2#serviceaccount

h) finally, just go through this example and replace the various
   account related data (marked with LOUD COMMENTS) with your own. Then run
   the script and admire the resulting appointment in your Google calendar.

   Heinrich Wilhelm Kloepping Sr, CISSP
   Sat Nov 10 17:20:40 GMT+1 2012
*/

/* THIS IS THE PATH TO THE GOOGLE LIBRARIES
*/
require_once 'google-api-php-client/src/Google_Client.php';
require_once 'google-api-php-client/src/contrib/Google_CalendarService.php';

/* CHANGE INTO YOUR SERVICE_ACCOUNT_NAME.
 * This is also the identity others need to allow as owner or writer
 * in their calendars if they want your application to access your calendar
 */
define('SERVICE_ACCOUNT_NAME', '999999...@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', '/some/path/to/the/<longhexstring>-privatekey.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)
 */
$client->setUseObjects(true);

/* 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_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_CalendarService($client);

$event = new Google_Event();
$event->setSummary('Dinner at Henk's house'); /* what to do, summary of the appointment */
$event->setLocation('Slochteren');            /* yes, it exists */

/* Now, set the start date/time
*/
$start = new Google_EventDateTime();
$start->setDateTime('2012-11-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_EventDateTime();
$end->setDateTime('2012-11-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_EventAttendee();
$attendee1->setEmail('he...@noreply.lan');
$attendees = array($attendee1);
$event->attendees = $attendees;

/* CREATE THE EVENT IN THE PROPER CALENDAR
*/
$createdEvent = $cal->events->insert('name-of-...@gmail.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();
}
?>



Blaine Lang

unread,
Nov 25, 2012, 12:57:41 AM11/25/12
to google-ca...@googlegroups.com
Fortean, your example was very helpful but I did run into a few additional issues getting this to work and wanted to add a few more details for what worked for me.

Don't forget to edit the config.php file that comes with the PHP library. There are quite a few settings in the config file which initially I updated but once I got it working, I commented out the settings until only the necessary settings were left. If you are only going to use the Service Account method, then you should only need to setup the 'developer_key' define - it NEEDS to be the API key value found in the API console for the Simple API access.

You will need to setup sharing on the calendar you want to access for reading or managing. I found it quite frustrating to get the calendar to allow me to add a sharing option for the API Service Account email address for anything other then basic view access. 
  • You need to enable the extra permissions in your google apps control panel - this is done under 'Settings -> Calendar. 
  • You need to review/update both the sharing settings for the default 'ORG' permissions as well as the sharing settings under the general sub tab.
  • Even after enabling the extended permissions, you may find you still can not add the API Service Account Email Address to still have anything other then basic view even thought you have now enabled it. Delete all browser cookies and session cookies and log back into your google calendar. Try adding a new calendar and see it will now let you. I found that it was necessary to do this a few times and it may just be a lag in the account permissions taking affect. It finally worked for me and now was able to Delete/Add/Update events
After the program was all working, I was able to remove the OAuth access grant made in your step (g) - so this step may not be needed.

I found that using the API Test console at https://developers.google.com/google-apps/calendar/v3/reference/events#resource was very helpful. Make sure you enable   the required access for each of the API methods. As you scroll down when viewing the selected API method detail, you will see the Try It label and just to the right is a toggle to grant access - it frequently gets toggled off so check that if you see it failed.

There is a lot of miss information in the online documentation between the different OAuth versions and API versions as well as the docs on the Service Accounts support for calendar and other API's is very much lacking. Your code fortean was very helpful - thanks!

$attendee1->setEmail('henk@noreply.lan');

$attendees = array($attendee1);
$event->attendees = $attendees;

/* CREATE THE EVENT IN THE PROPER CALENDAR
*/
$createdEvent = $cal->events->insert('name-of-cale...@gmail.com', $event);

D Bertrand

unread,
Jun 10, 2013, 8:20:40 PM6/10/13
to google-ca...@googlegroups.com
Blaine would you mind submitting a piece of code to demonstrate this, working with Google Calendar?

That would be awesome.

Mahesh M

unread,
Jul 24, 2013, 2:43:15 AM7/24/13
to google-ca...@googlegroups.com
hi Daniel,

with service account are you able to see the service account's calendar (UI). I mean is there a provision with service account to view the calendar?

Thanks

Daniel Fischer

unread,
Jul 24, 2013, 11:27:30 AM7/24/13
to google-calendar-api
I dont think I was ever able to see the calendar from the service account. You can access it via the api or view the calendar from your personal account if it has permissions. 


--
You received this message because you are subscribed to a topic in the Google Groups "Google Calendar API" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/google-calendar-api/MySzyAXq12Q/unsubscribe.

To unsubscribe from this group and all its topics, send an email to google-calendar...@googlegroups.com.
To post to this group, send email to google-ca...@googlegroups.com.

Josh Boddiford

unread,
Sep 4, 2013, 11:22:03 PM9/4/13
to google-ca...@googlegroups.com
Blaine,

Would you mind putting your successful source code out here on the forum? I'm having the same exact problems getting this to work and would really appreciate having some code to compare.

Thanks!
Josh

Teddy Aprilianto

unread,
Nov 2, 2014, 8:32:14 PM11/2/14
to google-ca...@googlegroups.com
Hi All,

Can we insert/update google calendar using service account without sharing the calendar to service account email ? I have 200 calendars that needs to be updated

Thanks
Teddy
Message has been deleted

Matias Azar

unread,
Nov 4, 2014, 10:22:34 PM11/4/14
to google-ca...@googlegroups.com
Hi. I have readed my calendar events...
how can i get (PHP API) the start and end datetime ??

thanks in advance

Matias Azar

unread,
Nov 5, 2014, 8:25:18 AM11/5/14
to google-ca...@googlegroups.com
UPDATE: I made it... $event->getStart()->getDateTime();

Zhang Xiangjun

unread,
Nov 6, 2014, 5:24:14 AM11/6/14
to google-ca...@googlegroups.com
Hi, Chet

would you mind send the demo code to me, thanks

Lucia Fedorova

unread,
Nov 13, 2014, 6:45:03 AM11/13/14
to google-ca...@googlegroups.com
Hi all, if you want to modify many calendars using a service account and they happen to be in the same domain, you can use a domain-wide delegation of authority: https://developers.google.com/drive/web/delegation (yes, the documentation is for drive but it should work the same way)

xiangjun

unread,
Nov 13, 2014, 10:02:47 PM11/13/14
to google-ca...@googlegroups.com
thanks a lot.

--
You received this message because you are subscribed to a topic in the Google Groups "Google Calendar API" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/google-calendar-api/MySzyAXq12Q/unsubscribe.
To unsubscribe from this group and all its topics, send an email to google-calendar...@googlegroups.com.
To post to this group, send email to google-ca...@googlegroups.com.
Visit this group at http://groups.google.com/group/google-calendar-api.
For more options, visit https://groups.google.com/d/optout.

Matt Erickson

unread,
Nov 24, 2014, 4:14:40 PM11/24/14
to google-ca...@googlegroups.com
Hey Lucia,

I followed that tutorial for a PHP application i maintain and my app is working about 50-60% of the time but i am getting 403 forbidden errors the other 40-50% of the time.  Very strange, very inconsistent.  Have you implemented this yourself or was that more of a blind link attempting to help?  Any thoughts would be appreciated.

~(ME)

Lucia Fedorova

unread,
Nov 24, 2014, 9:00:04 PM11/24/14
to google-ca...@googlegroups.com
Hi Matt,
is it possible that some of the calendars you are accessing are in a different domain? Which requests are failing for you?

Matt Erickson

unread,
Nov 24, 2014, 9:31:11 PM11/24/14
to google-ca...@googlegroups.com
I log my errors and the stack trace shows the following:

exception 'Google_Service_Exception' with message 'Error calling POST https://www.googleapis.com/calendar/v3/calendars/USER%40MYDOMAIN.com/events: (403) Forbidden' in /home/mySite/public_html/myDir/google-api-php-client/src/Google/Http/REST.php:76Stack trace:#0 /home/mySite/public_html/mySite_util/google-api-php-client/src/Google/Http/REST.php(41): Google_Http_REST::decodeHttpResponse(Object(Google_Http_Request))#1 /home/mySite/public_html/mySite_util/google-api-php-client/src/Google/Client.php(548): Google_Http_REST::execute(Object(Google_Client), Object(Google_Http_Request))#2 /home/mySite/public_html/mySite_util/google-api-php-client/src/Google/Service/Resource.php(190): Google_Client->execute(Object(Google_Http_Request))#3 /home/mySite/public_html/mySite_util/google-api-php-client/src/Google/Service/Calendar.php(1440): Google_Service_Resource->call('insert', Array, 'Google_Service_...')#4 /home/mySite/public_html/mySite/functions/createticket.php(193): Google_Service_Calendar_Events_Resource->insert('USER@MYDO...', Object(Google_Service_Calendar_Event))#5 {main}

Where MYDOMAIN and USER are replaced with legitimate values in the logs but removes for anon reasons here as well as the pathing for the server folders.  This request will 200 OK every 7/10 times but 3/10 fail with nothing but this logged.

Sergei Filatov

unread,
Oct 21, 2018, 2:27:09 AM10/21/18
to Google Calendar API
Bless you my friend! I spent 6 hours figuring out the problem, and that was pointed nowhere out. I love you ❤️
Reply all
Reply to author
Forward
0 new messages