Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to correctly obtain user's Calendar events using service account?

I'm trying to retrive Calendar events for a user in a domain. I have service account access, but i get 404 error when I try to get specific user events. Heres connection code:

NetHttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
    GoogleCredential credential = new GoogleCredential.Builder()
            .setTransport(httpTransport)
            .setJsonFactory(JSON_FACTORY)
            .setServiceAccountId(googleApiServiceAccountId)
            .setServiceAccountScopes(Collections.singleton(CalendarScopes.CALENDAR_READONLY))
            .setServiceAccountPrivateKey(SecurityUtils.loadPrivateKeyFromKeyStore(
                    SecurityUtils.getPkcs12KeyStore(),
                    getClass().getClassLoader().getResourceAsStream(googleApiPrivateKeyPath),
                    NOTASECRET, PRIVATEKEY, NOTASECRET))
            .build();

    calendarApi = new Calendar.Builder(httpTransport,
            JSON_FACTORY, credential).setApplicationName(getApplicactionName()).build();

Events listing method:

public List<Event> getCalendarEventsForUserAndDates(String userEmail, Long dateFrom, Long dateTo) {
    try {
        String pageToken = null;
        List<Event> allEvents = Lists.newArrayList();
        do {
            ArrayMap<String, Object> parameters = new ArrayMap<String, Object>();
            parameters.add("xoauth_requestor_id", userEmail);
            Calendar.Events.List list = calendarApiBean.getCalendarApi()
                    .events().list("primary");
            list.setTimeMax(new DateTime(dateFrom, 0))
                    .setTimeMin(new DateTime(dateTo, 0))
                    .setUnknownKeys(parameters);
            Events events = list.setPageToken(pageToken)
                    .execute();
            List<? extends Event> items = events.getItems();
            if (items != null) {
                allEvents.addAll(items);
            }
            pageToken = events.getNextPageToken();
        } while (pageToken != null);
        return allEvents;
    } catch (IOException e) {
        logger.error("error while retriving calendar events for {} and dates {} {} ", userEmail, dateFrom, dateTo);
        logger.error("exception", e);
        return Collections.emptyList();
    }

}

When i try to set xoauth_requestor_id to user's email and list 'primary', i get Calendar events for my Service Accounts. When I change events().list() parameter to user's email I get an following Error:

com.google.api.client.googleapis.json.GoogleJsonResponseException: 404 Not Found
{
  "code" : 404,
  "errors" : [ {
    "domain" : "global",
    "message" : "Not Found",
    "reason" : "notFound"
  } ],
  "message" : "Not Found"
}

Thanks for any help.

like image 929
mihn Avatar asked Jun 20 '13 10:06

mihn


People also ask

How do I share calendar with service account?

In the Calendars tab, click the Office 365 Connect button. Select the Connect with Service Account option. Enter the service account to use. A page listing the permissions required to access the Office 365 calendars display.


2 Answers

To solved this problem I had to add this service account to authorized API clients on Domain Administration. Client name is Service Account Client ID and scope was for Readonly Calendar

like image 61
mihn Avatar answered Oct 09 '22 11:10

mihn


This consists of two different parts

  1. Creating a service account
  2. Giving it permissions to access the scopes you need

Create the service account:

  1. Go to the cloud page to administer your Service Accounts: Menu on the left side -> IAM & admin -> Service accounts. Or click on this link: https://console.cloud.google.com/iam-admin/serviceaccounts
  2. Make sure you are logged in as the user you want to use, and check that the organization is correctly selected
  3. Create a new service account with Project Viewer role (you can change this later), and download the .json file with the credentials when you click to create a key.
  4. Edit the service account and enable G Suite Domain-wide Delegation
  5. Take note of the Client ID. (NOT the Key ID)

Give it permissions:

  1. Go to admin.google.com
  2. Make sure you are logged in as the user with admin rights.
  3. Then go to Security -> Settings -> Advanced settings -> Manage API client access
  4. In client name fill in the Client ID you copied above (NOT the Key id)
  5. Fill in the scopes you need and authorize the service account. ie:

    https://www.googleapis.com/auth/calendar.readonly,https://www.googleapis.com/auth/gmail.readonly
    

I tested the Python samples I link in the sources, and can confirm this works as expected.

Sources: https://developers.google.com/identity/protocols/OAuth2ServiceAccount https://support.google.com/a/answer/162106?hl=en

like image 38
Emilio Avatar answered Oct 09 '22 11:10

Emilio