Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing Google Contacts Api via OAuth 2.0 and private key aka Service Account

I am currently implementing access to Google Contacts via OAuth 2.0 and a so called Service Account. The service account is generated for an ordinary user like "[email protected]".

The code to generate the OAuth 2.0 credentials is:

public static GoogleCredential getCredentials() throws GeneralSecurityException, IOException {
    GoogleCredential credential = new GoogleCredential.Builder().setTransport(HTTP_TRANSPORT)
            .setJsonFactory(JSON_FACTORY)
            .setServiceAccountId(SingleUserCredentials.SERVICE_ACCOUNT_EMAIL)
            .setServiceAccountScopes("https://www.google.com/m8/feeds")
            .setServiceAccountPrivateKeyFromP12File(new File(SingleUserCredentials.SERVICE_ACCOUNT_PKCS12_FILE_PATH))
            .build();
    credential.refreshToken();
    return credential;
}

I am then trying to retrieve the contacts via:

    ContactsService myService = new ContactsService(
            "myApp");

    myService.setOAuth2Credentials(getCredentials());

    URL feedUrl = new URL("https://www.google.com/m8/feeds/contacts/default/full");
    Query myQuery = new Query(feedUrl);
    ContactFeed resultFeed = myService.query(myQuery, ContactFeed.class);
    // Print the results

    for (ContactEntry entry : resultFeed.getEntries()) {
        System.out.println(entry.getName().getFullName().getValue());
        System.out.println("Updated on: " + entry.getUpdated().toStringRfc822());
    }

The problem is that I do not get any a single contact from my account. The feed is always empty. There is no error. Nothing.

When accessing a Google Apps managed domain via the same approach it works nicely.

I am wondering if the Contacts Api supports OAuth 2.0 for ordinary (aka @gmail.com) accounts when using a p12 key file and a service account.

like image 652
Ra_ Avatar asked Nov 13 '22 13:11

Ra_


1 Answers

I ran into that same problem myself.

I tried both the email address that I received when I setup the key and the email address of a domain administrator.

When I use the email from the key setup, I don't receive anything at all -- no warnings, no exceptions, and no data.

When I use the email address of a domain administrator, I receive an exception:

com.google.api.client.auth.oauth2.TokenResponseException: 400 OK
     [java] {
     [java]   "error" : "invalid_grant"
     [java] }
     [java] Feb 5, 2013 5:16:48 PM com.google.appengine.repackaged.org.apache.http.impl.client.DefaultRequestDirector handleResponse
     [java] WARNING: Authentication error: Unable to respond to any of these challenges: {}
     [java] Feb 5, 2013 5:16:48 PM com.google.apphosting.utils.jetty.JettyLogger warn
     [java] WARNING: /
     [java] java.lang.NullPointerException: No authentication header information

...

So, I figured that the domain administrator's email address wasn't what I needed.

Next, I Googled around for a while before finding this page:

http://javadoc.google-api-java-client.googlecode.com/hg/1.13.2-beta/com/google/api/client/googleapis/auth/oauth2/GoogleCredential.html

I saw in there getServiceAccountUser (). The description of the field was:

Returns the email address of the user the application is trying to impersonate in the service account flow or null for none or if not using the service account flow.

Sure enough, there's a corresponding setServiceAccountUser (String) which accepts the username (email address) of the user you're using the service account to impersonate.

I set that field to an appropriate value and I was able to proceed.

In retrospect, it all makes sense -- if I don't supply an account that I'm trying to work from, I can't pull down the contacts for that account.

like image 162
Anonymous Avatar answered Nov 15 '22 05:11

Anonymous