简体   繁体   中英

Java Google Calendar api “access_denied” on Service Account

I'm trying to connect to a calendar using the Java Google Calendar api. The java application uses a service account.

I've the following code:

   java.io.File licenseFile = new java.io.File("39790cb51b361f51cab6940d165c6cda4dc60177-privatekey.p12");

   GoogleCredential credential = new GoogleCredential.Builder()

  .setTransport(HTTP_TRANSPORT)
  .setJsonFactory(JSON_FACTORY)
  .setServiceAccountId("xxx@developer.gserviceaccount.com") 
  .setServiceAccountUser(EMAIL_ADRESS)
  .setServiceAccountScopes(CalendarScopes.CALENDAR)
  .setServiceAccountPrivateKeyFromP12File(licenseFile)
  .build();

  client = new com.google.api.services.calendar.Calendar.Builder(
                        HTTP_TRANSPORT, JSON_FACTORY, credential)
                        .setApplicationName("Google Calendar Sync").build();

  Calendar calendar = client.calendars().get(EMAIL_ADRESS).execute();

On the last line I get an IOException with the message:

ex = (com.google.api.client.auth.oauth2.TokenResponseException) com.google.api.client.auth.oauth2.TokenResponseException: 400 Bad Request { "error" : "access_denied" }

I dubble checked the values for the GoogleCredential object and they are correct. I've also added https://www.google.com/calendar/feeds/ , http://www.google.com/calendar/feeds/ in my domain console with the application id as client to authorize third party application access

Am I forgetting a step?

The api isn't finished yet. More specifically the service account part.

The calendar owner needs to give permission to the application to read/write the calendar in it's calendar settings. It's found in the sharing settings of the calendar, there you can add e-mail adresses of accounts and give them permission on your calendar.

So in this case I had to add: xxx@developer.gserviceaccount.com to the permission/share list of the calendars the application needed access to.

I also deleted another post that didn't full work because of the issue above. I'll undelete it since it contains some code fragments that may help other people in the future. But beaware of the permission issues and service accounts not supporting Google Calendar

I got it to work

I don't know why but I deleted the line

.setServiceAccountUser(EMAIL_ADRESS)

Also I added an extra url in the domain scope:

https://apps-apis.google.com/a/feeds/calendar/resource/#readonly

and deleted a link that wasn't working.

Finally I changed the applicationName in my client declaration to the same name as in the api console

client = new com.google.api.services.calendar.Calendar.Builder(
                        HTTP_TRANSPORT, JSON_FACTORY, credential)
                        .setApplicationName("HolidaySyncs").build();

After these steps it started to work.

Also note for future reference after I did this I had the following error:

{
 "error": {
  "errors": [
   {
    "domain": "global",
    "reason": "notFound",
    "message": "Not Found"
   }
  ],
  "code": 404,
  "message": "Not Found"
 }
}

I solved this by changing for example:

Event result = client.events().insert(<EMAIL ADRESS>, event).execute();

to

Event result = client.events().insert("primary", event).execute();

First I tought there was something wrong with the google servers, but apparently it goes wrong when you try to link to a calendar ID. So linking to "primary" which is the primary calendar of an account works. But according to the documentation it should also work when you refer to a specific calendar ID, where the email address is the primary calendar. Probably a bug?

UPDATE: after these code correction I still had issues. Read the accepted answer for more information.

I do:

List find = client.events().list(EMAIL_ADRESS);
DateTime timeMin = new DateTime(DateUtil.stringToDate("01/01/2013"));
DateTime timeMax = new DateTime(DateUtil.stringToDate("01/02/2013"));

find.setTimeMin(timeMin);
find.setTimeMax(timeMax);

   try{
       Events events = find.execute();
       int i =0;

       while (true) {
           System.out.println("Page: "+(++i)+": "+events.getItems().size());
         for (Event event : events.getItems()) {
           System.out.println(event.getSummary());
         }
         String pageToken = events.getNextPageToken();
         if (pageToken != null && !pageToken.isEmpty()) {
           events = client.events().list(EMAIL_ADRESS).setPageToken(pageToken).execute();
         } else {
           break;
         }
       }

       }catch(GoogleJsonResponseException e){
           System.out.println(e.getMessage());
//         e.printStackTrace();
       }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM