Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NullPointerException only after I have setServiceAccountUser() for GoogleCredential object (Grails/Java)

I receive a NullPointerException with very little detail when I attempt to setServiceAccountUser(ACCOUNT_TO_IMPERSONATE) on my GoogleCredential, build a Google Tasks Service Object and subsequently try to send a request for a list of Tasks from ACCOUNT_TO_IMPERSONATE.

def credential = new GoogleCredential.Builder()
    .setTransport(HTTP_TRANSPORT)
    .setJsonFactory(JSON_FACTORY)
    .setServiceAccountId(SERVICE_ACCOUNT_ID)
    .setServiceAccountPrivateKeyFromP12File(P12_FILE)
    .setServiceAccountScopes(GOOGLE_TASK_SCOPES)
    .setServiceAccountUser(ACCOUNT_TO_IMPERSONATE)
    .build()

    credential.refreshToken()
    log.debug("Google Credential Impersonating: ${credential.getServiceAccountUser()}")

    def service = new com.google.api.services.tasks.Tasks.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential).build()

    return service

Please note that the credential.getServiceAccountUser() logs out the expected ACCOUNT_TO_IMPERSONATE.

There was a similar issue reported in https://github.com/googleads/googleads-java-lib/issues/19

StackTrace :
Caused by: java.lang.NullPointerException at com.google.api.client.repackaged.com.google.common.base.Preconditions.checkNotNull(Preconditions.java:191)
at com.google.api.client.util.Preconditions.checkNotNull(Preconditions.java:127)
at com.google.api.client.json.jackson2.JacksonFactory.createJsonParser(JacksonFactory.java:96)
at com.google.api.client.json.JsonObjectParser.parseAndClose(JsonObjectParser.java:85)
at com.google.api.client.json.JsonObjectParser.parseAndClose(JsonObjectParser.java:81)
at com.google.api.client.auth.oauth2.TokenResponseException.from(TokenResponseException.java:88)
at com.google.api.client.auth.oauth2.TokenRequest.executeUnparsed(TokenRequest.java:287)
at com.google.api.client.auth.oauth2.TokenRequest.execute(TokenRequest.java:307)
at com.google.api.client.auth.oauth2.Credential.executeRefreshToken(Credential.java:570)
at com.google.api.client.googleapis.auth.oauth2.GoogleCredential.executeRefreshToken(GoogleCredential.java:247)
at com.google.api.client.auth.oauth2.Credential.refreshToken(Credential.java:489)
at com.google.api.ads.common.lib.auth.OAuth2Helper.callRefreshToken(OAuth2Helper.java:70)
at com.google.api.ads.common.lib.auth.OfflineCredentials.generateCredential(OfflineCredentials.java:144)
...

The lack of detail in the error was said to be an issue in older versions of Google Tasks but I have upgraded to the latest version and see no difference.

compile "com.google.api-client:google-api-client:1.19.0"
compile 'com.google.apis:google-api-services-tasks:v1-rev41-1.19.0'

EDIT: After tinkering with the code in the grails console in our web application I can see that executing credential.refreshToken() causes the NPE when ServiceAccountUser is set.

When I unset the ServiceAccountUser, refreshToken() is successful. Additionally, trying to retrieve a list of Google Tasks is succcessful for the Service account when the ServiceAccountUser is not set.

Any help would be greatly appreciated.

like image 788
stevenm Avatar asked Dec 17 '14 09:12

stevenm


1 Answers

I discovered the reason for the behaviour we were experiencing, but thanks for your suggestions, none-the-less, user1807337 & Srinivasan.

We need to get our application's users to delegate domain-wide authority to our application. This can be done by the organisataion's google apps admin, following the instructions in the sub-section entitled Delegating domain-wide authority to the service account

https://developers.google.com/accounts/docs/OAuth2ServiceAccount

Here is the explanation given in the same resource: "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..."

like image 50
stevenm Avatar answered Sep 21 '22 13:09

stevenm