6

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("steve.smith@reco.se")
                    .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!

jakob
  • 5,979
  • 7
  • 64
  • 103

1 Answers1

6

Did you try the single scope:

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

and,

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

should be

 .setServiceAccountId("2363681XXXX@developer.gserviceaccount.com")

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

also, see this related question

Community
  • 1
  • 1
Jasper Duizendstra
  • 2,587
  • 1
  • 21
  • 32
  • Hmm getting a com.google.api.client.googleapis.json.GoogleJsonResponseException: 500 Internal Server Error { "code" : 500, "errors" : [ { "domain" : "global", "message" : "Internal Error", "reason" : "internalError" } ], "message" : "Internal Error" } – jakob Nov 07 '12 at 07:29
  • It took me a while to get this working. My suggestion is to create a clean example, maybe even a new app in the api console. Remove all the analytics stuff, and focus only on the first step, creating the drive document. Or, skip the creation of the drive document for now, create one manually and use that one for the spreadsheet stuff. Try to isolate the problem. I do get those 500 errors also, but randomly and rarely. – Jasper Duizendstra Nov 07 '12 at 07:36
  • I found this http://stackoverflow.com/questions/12511656/google-drive-500-internal-error and tried to create a folder instead: file.setMimeType("application/vnd.google-apps.folder"); No error there. Let's say that this worked? Where do I find this folder? – jakob Nov 07 '12 at 07:46
  • If you created a folder, you created a google drive file, concept is the same. So yes it worked. Log in as the user ("steve.smith@reco.se") and look at the drive – Jasper Duizendstra Nov 07 '12 at 07:51
  • Omg it worked! YEE HAA! Could you change your answer to include the link to the 500 error and I will check them. One more question did you have to create a folder before or do you already have a folder? – jakob Nov 07 '12 at 07:56
  • Great news. (Link to where? I do not understand that, or do you mean linking this question to the other question?). I did not start with creating a folder to get it to work. – Jasper Duizendstra Nov 07 '12 at 07:59
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/19196/discussion-between-jakob-and-jasper-duizendstra) – jakob Nov 07 '12 at 08:09