Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Invalid grant when calling Java Google Drive Api with Service Account

Ok! As the title states I'm having some serious issues with the authentication when using a Service Account. So let's start from the beginning since it feels that I have tried everything!

Services set to on:

enter image description here

Drive SDK setup:

enter image description here

Service Account Api Access:

enter image description here

Api client access as described here: http://support.google.com/a/bin/answer.py?hl=en&answer=162106

enter image description here

The code:

public static void callSpreadsheetApi() {

        GoogleCredential credential = null;
        try {
            credential = new GoogleCredential.Builder().setTransport(HTTP_TRANSPORT)
                    .setJsonFactory(JSON_FACTORY)                    
                    .setServiceAccountId("2363XXXXXX19.apps.googleusercontent.com")                    
                    .setServiceAccountScopes(DriveScopes.DRIVE, "https://spreadsheets.google.com/feeds", "https://docs.google.com/feeds")
                    .setServiceAccountPrivateKeyFromP12File(new File("/Users/stevesmith/Desktop/c02e064935d33c3389f6ab1dbf9ea747a5bdaac5-privatekey.p12"))
                    .setServiceAccountUser("[email protected]")
                    .build();

        } catch (GeneralSecurityException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }


        Drive drive = new Drive.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential).build();

        com.google.api.services.drive.model.File  file = new com.google.api.services.drive.model.File();
        file.setTitle("test");
        file.setMimeType("application/vnd.google-apps.spreadsheet");
        Drive.Files.Insert insert = null;
        try {
            insert = drive.files().insert(file);
            file = insert.execute();
        } catch (IOException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
}

The exception:

[info] play - Application started (Dev)
com.google.api.client.auth.oauth2.TokenResponseException: 400 Bad Request
{
  "error" : "invalid_grant"
}
    at com.google.api.client.auth.oauth2.TokenResponseException.from(TokenResponseException.java:103)
    at com.google.api.client.auth.oauth2.TokenRequest.executeUnparsed(TokenRequest.java:303)
    at com.google.api.client.auth.oauth2.TokenRequest.execute(TokenRequest.java:323)
    at com.google.api.client.googleapis.auth.oauth2.GoogleCredential.executeRefreshToken(GoogleCredential.java:340)
    at com.google.api.client.auth.oauth2.Credential.refreshToken(Credential.java:505)
    at com.google.api.client.auth.oauth2.Credential.intercept(Credential.java:266)
    at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:857)
    at com.google.api.client.googleapis.json.GoogleJsonResponseException.execute(GoogleJsonResponseException.java:182)
    at com.google.api.client.googleapis.services.GoogleClient.executeUnparsed(GoogleClient.java:279)
    at com.google.api.client.http.json.JsonHttpRequest.executeUnparsed(JsonHttpRequest.java:207)
    at com.google.api.services.drive.Drive$Files$Insert.executeUnparsed(Drive.java:307)
    at com.google.api.services.drive.Drive$Files$Insert.execute(Drive.java:331)
    at services.GoogleService.callSpreadsheetApi(GoogleService.java:236)
    at controllers.Application.index(Application.java:26)
    at Routes$$anonfun$routes$1$$anonfun$apply$1$$anonfun$apply$2.apply(routes_routing.scala:32)
    at Routes$$anonfun$routes$1$$anonfun$apply$1$$anonfun$apply$2.apply(routes_routing.scala:32)
    at play.core.Router$HandlerInvoker$$anon$5$$anon$1.invocation(Router.scala:1090)
    at play.core.j.JavaAction$$anon$1.call(JavaAction.scala:33)
    at play.core.j.JavaAction$class.apply(JavaAction.scala:74)
    at play.core.Router$HandlerInvoker$$anon$5$$anon$1.apply(Router.scala:1089)
    at play.core.ActionInvoker$$anonfun$receive$1$$anonfun$6.apply(Invoker.scala:126)
    at play.core.ActionInvoker$$anonfun$receive$1$$anonfun$6.apply(Invoker.scala:126)
    at play.utils.Threads$.withContextClassLoader(Threads.scala:17)
    at play.core.ActionInvoker$$anonfun$receive$1.apply(Invoker.scala:125)
    at play.core.ActionInvoker$$anonfun$receive$1.apply(Invoker.scala:115)
    at akka.actor.Actor$class.apply(Actor.scala:318)
    at play.core.ActionInvoker.apply(Invoker.scala:113)
    at akka.actor.ActorCell.invoke(ActorCell.scala:626)
    at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:197)
    at akka.dispatch.Mailbox.run(Mailbox.scala:179)
    at akka.dispatch.ForkJoinExecutorConfigurator$MailboxExecutionTask.exec(AbstractDispatcher.scala:516)
    at akka.jsr166y.ForkJoinTask.doExec(ForkJoinTask.java:259)
    at akka.jsr166y.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:975)
    at akka.jsr166y.ForkJoinPool.runWorker(ForkJoinPool.java:1479)
    at akka.jsr166y.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:104)

I've been browsing the web for the past 3 hours and all of the PHP and Python folks seem to have solved it by setting the correct time on their linux production server. I'm sitting in MacOS Snow Leopard and I have tried with the time setting but no luck there. I have also tried to create a new key. Changing the scopes. Adding different ServiceAccountUsers and so on. I'm probably missing some crucial part or maybe it's supersimple? I'm running out of ideas!

like image 262
jakob Avatar asked Nov 06 '12 15:11

jakob


People also ask

What is Google API services drive?

The Google Drive API allows you to create apps that leverage Google Drive cloud storage. You can develop applications that integrate with Drive, and create robust functionality in your application using the Drive API.

How do I find my Google Drive API key?

To create an API key: Navigate to the APIs & Services→Credentials panel in console. Select Create credentials, then select API key from the dropdown menu. The API key created dialog box displays your newly created key.


1 Answers

Did you try the single scope:

 .setServiceAccountScopes("https://www.googleapis.com/auth/drive")

and,

 .setServiceAccountId("23636812XXXX.apps.googleusercontent.com") 

should be

 .setServiceAccountId("[email protected]")

The other scopes are required for the Spreadsheets, they are not required (yet).

also, see this related question

like image 192
Jasper Duizendstra Avatar answered Oct 19 '22 08:10

Jasper Duizendstra