使用服务帐户创建Google日历事件时出错 [英] Error while creating google calendar event with a service account

查看:107
本文介绍了使用服务帐户创建Google日历事件时出错的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要在日历上创建一个Google日历活动,并将其他用户添加为该活动的参与者.目的是在未经用户同意的情况下将日历事件发送给应用程序用户(O-Auth).

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 ).

在阅读Google的文档后,我发现我需要一个服务帐户.因此,我使用G-Suite的电子邮件地址之一noreply@xxxxx.com创建了一个项目和一个服务帐户,并为其启用了日历API.

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.

我创建并下载了内容为的密钥对(JSON)

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;
    }

credential 对象具有密钥文件中的大多数详细信息.但是,字段 serviceAccountUser accessToken refreshToken clientAuthentication requestInitializer null 值.(我猜这里有问题)

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 )

现在,使用 credentialObject ,我继续根据文档编写代码以创建事件.

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());

但是,这导致了错误

{
  "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."
}

花了很多时间在 Domain-Wide委托上之后,我了解到,如果我们必须从g套件中以其他用户的身份发送事件,这是必需的,这对我来说不是必需的.但是,为了进行调试,我继续提供了 Domain-Wide委托并重新运行了该程序.再次出现相同的错误.

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.

因此,我从 event 对象中删除了被邀请者/与会者,然后重新运行了该应用程序.这次程序运行没有任何错误,但是生成的事件链接在单击时显示找不到请求的事件.

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.

我在Google开发人员链接上没有看到通过Java客户端库使用服务帐户的任何示例.

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

能否让我知道这里出了什么问题,以及有关如何从我的项目中确切创建Google日历事件的官方/工作文档中添加了其他(以及非g套件)用户来添加为与会者,所以我不必征得其他用户的同意即可将事件添加到他们自己的日历中?

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?

谢谢.

推荐答案

首先要说的是,如果您遇到很多问题,这是新内容,而没有说明的教程则需要这样做由于服务帐户过去曾经能够发送邀请,因此Google大约在一年前就将其锁定了.

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.

这应该可以工作,但是我没有对其进行测试,因为我再也无法访问Gsuite帐户.您需要让gsuite管理员设置域范围委派给其他用户.然后,服务帐户需要模拟该用户,以便该帐户显示为该用户是发送邀请的用户.

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.

我唯一的添加方式示例是.net

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

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

            }.FromCertificate(certificate);

Java示例猜测

我不是Java开发人员,但是.net客户端库和Java客户端库的开发方式非常接近.我猜您正在寻找一种名为setServiceAccountUser

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
  • 这篇关于使用服务帐户创建Google日历事件时出错的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆