Calendar API v3, 2-legged OAuth & Java

Wednesday, December 14, 2011 | 5:21 PM

Labels: ,

2-Legged OAuth is a useful authorization mechanism for apps that need to manipulate calendars on behalf of users in an organization. Both developers building apps for the Google Apps Marketplace and domain administrators writing tools for their own domains can benefit. Let’s take a look at how to do this with the new Calendar API v3 and Java client library 1.6.0 beta.

To get started as a domain administrator, you need to explicitly enable the new Google Calendar API scopes under Google Apps cPanel > Advanced tools > Manage your OAuth access > Manage third party OAuth Client access:

The scope to include is:

    https://www.googleapis.com/auth/calendar

To do the same for a Marketplace app, include the scope in your application's manifest.

Calendar API v3 also needs an API access key that can be retrieved in the APIs Console. Once these requirements are taken care of, a new Calendar service object can be initialized:

  public Calendar buildService() {
    HttpTransport transport = AndroidHttp.newCompatibleTransport();
    JacksonFactory jsonFactory = new JacksonFactory();

    // The 2-LO authorization section
    OAuthHmacSigner signer = new OAuthHmacSigner();
    signer.clientSharedSecret = "<CONSUMER_SECRET>";

    final OAuthParameters oauthParameters = new OAuthParameters();
    oauthParameters.version = "1";
    oauthParameters.consumerKey = "<CONSUMER_KEY>";
    oauthParameters.signer = signer;

    Calendar service = Calendar.builder(transport, jsonFactory)
      .setApplicationName("<YOUR_APPLICATION_NAME>")
      .setJsonHttpRequestInitializer(new JsonHttpRequestInitializer() {
        @Override
        public void initialize(JsonHttpRequest request) {
          CalendarRequest calendarRequest = (CalendarRequest) request;
          calendarRequest.setKey("<YOUR_API_KEY>");
        }
      }).setHttpRequestInitializer(oauthParameters).build();
    return service;
  }

Once the Calendar service object is properly initialized, it can be used to send authorized requests to the API. To access calendar data for a particular user, set the query parameter xoauth_requestor_id to a user’s email address:

  public void printEvents() {
    Calendar service = buildService();
    
    // Add the xoauth_requestor_id query parameter to let the API know
    // on behalf of which user the request is being made.
    ArrayMap customKeys = new ArrayMap();
    customKeys.add("xoauth_requestor_id", "<USER_EMAIL_ADDRESS>");

    List listEventsOperation = service.events().list("primary");
    listEventsOperation.setUnknownKeys(customKeys);
    Events events = listEventsOperation.execute();

    for (Event event : events.getItems()) {
      System.out.println("Event: " + event.getSummary());
    }
  }

Additionally, if the same service will be used to send requests on behalf of the same user, the xoauth_requestor_id query parameter can be set in the initializer:

  // …
  Calendar service = Calendar.builder(transport, jsonFactory)
    .setApplicationName("<YOUR_APPLICATION_NAME>")
    .setJsonHttpRequestInitializer(new JsonHttpRequestInitializer() {
       @Override
       public void initialize(JsonHttpRequest request) {
         ArrayMap customKeys = new ArrayMap();
         customKeys.add("xoauth_requestor_id", "<USER_EMAIL_ADDRESS>");
         calendarRequest.setKey("<YOUR_API_KEY>");
         calendarRequest.setUnknownKeys(customKeys);
       }
    }).setHttpRequestInitializer(oauthParameters).build();
  // ...

We hope you’ll try out 2-Legged OAuth and let us know what you think in the Google Calendar API forum.


Alain Vongsouvanh   profile

Alain is a Developer Programs Engineer for Google Apps with a focus on Google Calendar and Google Contacts. Before Google, he graduated with his Masters in Computer Science from EPITA, France.

8 comments:

Carber said...

Hi, i need to do this, but i'm using .net and csharp !

And i don't understand how to do this for .net from java

Can you explain ? please !

Matt Davies said...

I'm going to be starting to port this into ruby if anyone's interested. If anyone has already done this, they could save me some time and post it up :-)

I'll add some error checking and maybe even some tests then, ooooooh!!

Seema Khandkar said...

I am migrating from OAuth API 1.0a to OAuth 2.0 and this code is not working for me to access a user's Calendar events. I get GoogleJsonResponseException: 401 Unauthorized. I am using domain consumer key and consumer secret. I also generated an API key from the API console. What is the applicationName? Where can I get that? FYI - I am using google-api-client 1.6.0-beta and google-api-services-calendar v3-1.3.1-beta. Any help would be much appreciated.
Thanks.

ozzierod said...

I need this for PHP

Tim said...

This has been working for me up until a few months ago, now I get the following error:

Exception in thread "main" com.google.api.client.googleapis.json.GoogleJsonResponseException: 401 Unauthorized
{
"code" : 401,
"errors" : [ {
"domain" : "global",
"location" : "Authorization",
"locationType" : "header",
"message" : "Invalid Credentials",
"reason" : "authError"
} ],
"message" : "Invalid Credentials"
}
at com.google.api.client.googleapis.json.GoogleJsonResponseException.from(GoogleJsonResponseException.java:143)

Who can I contact for help regarding this?

Fer said...

Does anybody know if this 2-legged oauth works in write mode to Contact API or Provisioning API?

It seems Google that guys doesn't documented that these APIs are accesible in read-only mode, even using an OAuth domain key :-S

See: this example ,another one or this one.

MichaƂ Ziober said...

Hi. I have added linked question to this post. This is a link to the question: http://stackoverflow.com/questions/14852932/list-google-calendar-events-for-different-users

Could you answer on it on StackOverflow or on this service?

Could you help me with that problem?

Haithem Gazzah said...

can you give an exemple without using the google-api-client library?
for some reason related to the architectur of our project we can't afford to use google's api library