Error while creating google calendar event with a service account

穿精又带淫゛_ 提交于 2021-01-04 07:17:12

问题


I have a requirement of creating a google calendar event on a calendar and add other users as attendees to that event. The objective is to send calendar events to the application users without taking their consent ( O-Auth ).

After reading Google's documentation, I found out that I need a service account. So I created a project and a service account from one of the email addresses of our G-Suite, noreply@xxxxx.com and enabled calendar API for the same.

I created and downloaded a key pair ( JSON ) whose content is,

{
  "type": "service_account",
  "project_id": "*****",
  "private_key_id": "bdbbcd**************49f77d599f2",
  "private_key": "**"
  "client_email": "******@*****.iam.gserviceaccount.com",
  "client_id": "11083******576856",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/****dev%40*****kdev.iam.gserviceaccount.com"
}

And as per the documentation, I proceded to write authentication flow code,

public static GoogleCredential doOauth( String credsPath ) throws IOException
    {
        GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream(credsPath))
                .createScoped(Collections.singleton(CalendarScopes.CALENDAR));
        System.out.println(credential);
        return credential;
    }

The credential object has most of the details from the key file. But, the fields, serviceAccountUser, accessToken, refreshToken, clientAuthentication and requestInitializer have null value. ( I am guessing something wrong here )

Now, using the credentialObject, I continued to write the code as per the documentation to create the event.

GoogleCredential credential = doOauth(CREDENTIALS_FILE_PATH);
        Event event = new Event().setSummary("Google I/O 2015").setLocation("800 Howard St., San Francisco, CA 94103")
                .setDescription("A chance to hear more about Google's developer products.");
        final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();

        DateTime startDateTime = new DateTime("2020-12-28T09:00:00-07:00");
        EventDateTime start = new EventDateTime().setDateTime(startDateTime).setTimeZone("America/Los_Angeles");
        event.setStart(start);

        DateTime endDateTime = new DateTime("2020-12-28T17:00:00-07:00");
        EventDateTime end = new EventDateTime().setDateTime(endDateTime).setTimeZone("America/Los_Angeles");
        event.setEnd(end);

        String[] recurrence = new String[] { "RRULE:FREQ=DAILY;COUNT=2" };
        event.setRecurrence(Arrays.asList(recurrence));

        EventAttendee[] attendees = new EventAttendee[] { new EventAttendee().setEmail("myemailaddress@gmail.com.com") };
        event.setAttendees(Arrays.asList(attendees));

        EventReminder[] reminderOverrides = new EventReminder[] {
                new EventReminder().setMethod("email").setMinutes(24 * 60),
                new EventReminder().setMethod("popup").setMinutes(10), };
        Event.Reminders reminders = new Event.Reminders().setUseDefault(false)
                .setOverrides(Arrays.asList(reminderOverrides));
        event.setReminders(reminders);
        String calendarId = "primary";
        Calendar service = new Calendar.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential)
                .setApplicationName("testapp").build();
        event = service.events().insert(calendarId, event).execute();
        System.out.printf("Event created: %s\n", event.getHtmlLink());

But, this resulted in the error,

{
  "code" : 403,
  "errors" : [ {
    "domain" : "calendar",
    "message" : "Service accounts cannot invite attendees without Domain-Wide Delegation of Authority.",
    "reason" : "forbiddenForServiceAccounts"
  } ],
  "message" : "Service accounts cannot invite attendees without Domain-Wide Delegation of Authority."
}

After spending time on Domain-Wide Delegation, I understood that this is needed if we have to send the event as other user from our g-suite, which is not needed for my problem. But, to debug, I went ahead and provided Domain-Wide Delegation and re ran the program. The same error came again.

So, I removed the invitees/attendees from the event object and re ran the application. This time the program ran without any error, but the event link generated, on click says, Could not find the requested event.

I do not see any examples of using the service account via java client libraries on the google developer link.

Can you please let me know what is going wrong here and the official/working documentation on how exactly to create a google calendar event from my project add other ( non g suite as well ) users to add as attendees, so that I do not have to get consent from other users to add events to their own calendar?

Thank You.


回答1:


Fist off I want to say that this is something new, if you are seeing a lot of questions, and tutorials that did not state you needed to do this its because service accounts used to be able to send invites, this is something google locked down about a year ago.

This should work but i have not tested it as i no longer have access to a Gsuite account. You need to have the gsuite admin set up domain wide delegation to anther user. Then the service account needs to impersonate that user so it will appear as that user is the one sending the invites.

The only example I have for how that is added is in .net

.net example

var gsuiteUser = "se@clawskeyboard.com";
var serviceAccountCredentialInitializer = new ServiceAccountCredential.Initializer(serviceAccount)
            {
                User = gsuiteUser,
                Scopes = new[] { GmailService.Scope.GmailSend, GmailService.Scope.GmailLabels }

            }.FromCertificate(certificate);

Java example guess

I am not a java dev but the .net client library and the Java client library are very close in how they were developed. I would guess that you are looking for a method called setServiceAccountUser

GoogleCredential credential = new  GoogleCredential.Builder().setTransport(HTTP_TRANSPORT)
                .setJsonFactory(JSON_FACTORY)
                .setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
                .setServiceAccountScopes(CalendarScopes.CALENDAR)
                .setServiceAccountPrivateKeyFromP12File(credsPath))
                .setServiceAccountUser(gsuiteUser)
                .build();
  • OAuth2 for Service Accounts


来源:https://stackoverflow.com/questions/65368884/error-while-creating-google-calendar-event-with-a-service-account

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!