如何代表其他用户创建 Google 日历事件?

How to create Google Calendar events on behalf of another user?

我想实现一个日程安排应用程序,其中 X 可以在特定时间创建事件并将其添加到他们的 Google 日历中。然后 Y 应该能够注册同一事件并将其添加到他们的 Google 日历中。 X 人也应该能够重新安排活动。我在理解如何设计时遇到了一些困难,希望得到一些指点。

所以 X 可以在客户端进行身份验证并创建事件,但随后服务器需要存储该事件 ID,以便 Y 可以注册。但是服务器如何代表 X 邀请 Y 呢?我正在尝试使用服务帐户进行身份验证,但当我尝试创建邀请服务器端并添加与会者时,我得到了 There was an error contacting the Calendar service: Error: Service accounts cannot invite attendees without Domain-Wide Delegation of Authority.。这似乎是一个基本问题,服务帐户无法邀请随机参与者,除非他们在 GSuite 域中。

像 Calendly 这样的应用程序基本上可以做到这一点(你可以在别人的日历上注册,然后受邀参加他们组织的 Google 日历活动),所以我相信这是可行的。

这是我的基本测试代码:它在没有 attendees 字段的情况下工作,但如果设置它则会失败并出现上述错误。

import { google } from 'googleapis'
import * as SERVICE_ACCOUNT from './service-account.json'

const SCOPES = 'https://www.googleapis.com/auth/calendar';

const auth = new google.auth.JWT(
    SERVICE_ACCOUNT.client_email,
    null,
    SERVICE_ACCOUNT.private_key,
    SCOPES
)

console.log("Testing Google Calendar API")

const api = google.calendar({version : "v3", auth : auth})

api.events.insert({
    calendarId: '{CALENDAR}@group.calendar.google.com',
    requestBody: { 
        summary: 'Dope Test Event',
        description: 'Wow this works!',
        start: { dateTime: '2020-12-28T09:00:00-07:00', timeZone: 'America/Los_Angeles' },
        end: { dateTime: '2020-12-28T10:00:00-07:00', timeZone: 'America/Los_Angeles' },
        attendees: [
            { email: '{EMAIL}@gmail.com' } // works without this
        ] 
    }},
    function (err, res) {
        if(err) {
            console.log(err)
        } else {
            console.log(res)
        }
    }
)

如错误信息所述:

Service accounts cannot invite attendees without Domain-Wide Delegation of Authority.

因此,您需要设置域范围的委派,这将允许服务帐户模拟用户 - 即代表用户行事。

要设置全域委派:

  • 在 GCP 控制台中,通过继续 Actions-> Edit
  • ,勾选您正在使用的服务帐户的复选框 Enable G Suite Domain-wide Delegation
  • Enable the necessary scopes 通过继续 Security > API controls. 在您的管理控制台中委派服务帐户 修改您的代码如下:
const auth = new google.auth.JWT(
    SERVICE_ACCOUNT.client_email,
    null,
    SERVICE_ACCOUNT.private_key,
    SCOPES,
    USER_EMAIL 
)

其中 USER_EMAIL 是服务帐户应模拟的域用户的电子邮件。

推荐阅读:

https://developers.google.com/identity/protocols/oauth2/service-account#authorizingrequests