23
votes

Let's say I have a Google account [email protected] with project project-1 (configured as Google App Engine application in Google Developer Console) and a service account with e-mail address [email protected] that belong to it.

I know how to use this service account to create a calendar and manipulate its entries programmatically: I use the Google APIs Client Library (Java version, with service account´s credentials) to invoke Google Calendar API inside my Google App Engine application and it does just that. However any such created calendars seem to be distinctly owned by the service account, not by my englobing Google account. I conclude this from the following observations:

  • When I view my Google account's calendar in the Google Calendar UI, none of the programmatically created calendars show up under My calendars.
  • When I try to access such a calendar by issuing Other calendars | Add a friend´s calendar and with the service account´s email-address, I can send off the request, but it never gets answered (presumably because the service account's e-mail address isn't a "real" e-mail address).
  • When I'm creating calendars programmatically, I don't set CalendarListEntry#hidden, so the default false should apply.

So my question is this: How can I access calendars and calendar entries that were created programmatically with Google Calendar API (and a Java client in my case) in the normal Google Calendar Web UI. E.g., can the service account share its calendars with its owning Google account, or can I directly manipulate the Google account's calendars with its service account credentials in the UI.

I realize there are some previous questions on the same topic, but they haven't helped to solve the mystery for me so far.

3
hey there, I think we're kind of trying to do the same things. could you check this question please? What would you do when you want to update multi people's calendars? stackoverflow.com/questions/23469075/…Jinzhao Huo
@JinzhaoHuo It now works for me with a service account (and in Java) -- see accepted answer. If you have multiple people's calendars you may have to use multiple service accounts ...Drux
Thanks, but I don't think so. For example, assume there're 100 employees in my company, and I have to build 100 service accounts for updating their calendars? Doesn't seem to make sense. Maybe I have to rebuild the google client and calendar service for each employee, and having the service account impersonating the employee.Jinzhao Huo
@JinzhaoHuo I see your point. However, since I am unfamiliar with (the semantics of) domain consume keys I can't be of further help re your linked question.Drux

3 Answers

20
votes

You will have to programmatically share the calendar created by the service account. The calendars are owned by the service account.

What you tried :

  • the calendars don't show up in your account because you have no right to access them, even though you are the appengine admin.
  • entering the e-mail address of the service account does not show up the calendar in the UI because the e-mail address of the service account is not the e-mail address of the calendar. One service account could create multiple calendars.

Share the calendar programmatically with your account, log the calendar unique id and then enter it in the UI.

1
votes

According to the (outdated) documentation, you have to call .setServiceAccountUser("[email protected]") and the event will show up on that user's Calendar.

https://developers.google.com/identity/protocols/OAuth2ServiceAccount#authorizingrequests

Delegate domain-wide authority
If you have delegated domain-wide access to the service account and you want to impersonate a user account, specify the email address of the user account with the setServiceAccountUser method of the GoogleCredential factory. For example:

GoogleCredential credential = new GoogleCredential.Builder()
    .setTransport(httpTransport)
    .setJsonFactory(JSON_FACTORY)
    .setServiceAccountId(emailAddress)
    .setServiceAccountPrivateKeyFromP12File(new File("MyProject.p12"))
    .setServiceAccountScopes(Collections.singleton(SQLAdminScopes.SQLSERVICE_ADMIN))
    .setServiceAccountUser("[email protected]")
    .build();

It has to be a service account for a GSuite domain, and you have to enable GSuite Domain-wide Delegation.

0
votes

I thought you had to create the calendar with a PRN parameter (Which pretty much spoofs your existing google account address onto the "owner's" identity of the calendar)

using the prn parameter therefore will allow you to use the service account authentication to ( for example ) add events in your name (google address).

If found a discussion using the prn parameter