【问题标题】:Google Calendar API Service Account ErrorGoogle Calendar API 服务帐户错误
【发布时间】:2026-02-19 17:50:01
【问题描述】:

我收到这个错误

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

已经关注了 https://developers.google.com/admin-sdk/directory/v1/guides/delegation

我正在使用这个库并在 laravel 5.7 上运行它:https://github.com/spatie/laravel-google-calendar

有什么办法可以解决这个问题。请帮忙。

【问题讨论】:

  • 如果您能提供有关如何验证服务帐户的更多信息,那就太好了?您是否真的试图冒充其他用户?请粘贴一些代码以尝试重现您的问题,如this page 所示。还可以尝试在How to Ask page 之后改进您的问题。
  • @Raserhin 这里有同样的问题,不想创建一个新问题。我使用 GoogleCredential(在 .NET Core 后端)进行身份验证,并且服务帐户不会模拟某人。它具有域范围的权限和范围 [Calendar, CalendarEvents]。一切正常(甚至创建日历事件),但是当我在创建事件时添加 EventAttendees 时,它返回错误 OP 已发布。
  • 嗨@Nathan,如果您正在设置所有内容但没有执行最后一步,您不仅需要授予服务帐户域范围的授权,还需要“模拟”您域中的一个人您将代表服务帐户(出于垃圾邮件和安全原因,在此方法中不允许这样做)而不是您域的用户执行您的代码。
  • @Raserhin 感谢您的回复!我该怎么做呢?
  • 如果您只是想要一些指示,您可以查看这些页面(12)。如果您需要更多,可以创建另一个问题,发布您的代码并解释您的设置和问题。

标签: php google-api google-calendar-api google-oauth


【解决方案1】:

以下是完成这项工作的步骤:

在您的服务帐户中启用域范围委派

1 - 为您的服务帐号提供日历范围

2 - 您的用户需要具有角色服务帐户令牌创建者

3 - 在您将模拟的帐户中创建日历

服务帐户没有日历,因此您必须创建自己的日历

  • 使用您想要拥有日历的电子邮件登录https://calendar.google.com/(我使用了不同的帐户,与我要模拟的帐户不同,也许它可以使用模拟帐户中的日历)
  • 创建日历
  • 与有权修改和管理日历的服务帐户共享日历
  • 与您将模拟的具有修改和管理日历权限的帐户共享日历

创建谷歌客户端

  • 验证您的服务帐户。 (我使用了 JSON 密钥,我不确定其他身份验证是否适用于此目的)

代码示例:(我使用了 PHP,但我认为其他语言非常相似,因此您可以以此为指导)

请注意,使用一些电子邮件进行 IMPERSONALIZATION 至关重要。否则,403 错误会一直存在,请使用它进行身份验证,详情请参阅 Maksym Kalin 响应。

$google_client = new Google_Client();
$google_client->setAuthConfig($LOCATION_OF_JSON_KEY);
$google_client->setAccessType( 'offline' );
$google_client->setSubject('EmailToImpersonate@SomeAddress.com');
$google_client->setApplicationName("YourApplicationName");
$google_client->setScopes([\Google_Service_Calendar::CALENDAR, \Google_Service_Calendar::CALENDAR_EVENTS]);

与受邀者一起创建活动 :) 并享受!

注意: 通过这种方法,您可以创建活动并邀请人们参加。请记住 G Suite https://support.google.com/a/answer/2905486 的限制,因此如果您想创建许多活动,您将需要一个服务帐户池和一个日历池。

【讨论】:

  • 在我这边(使用 PHP api 2.7),这还不够:我还必须在 API 文档中似乎没有记录的地方设置一些权限。此权限必须从页面设置:admin.google.com/ac/owl/domainwidedelegation:您必须授予对 2 个范围“googleapis.com/auth/calendar”、“googleapis.com/auth/calendar.events”的权限。删除它们会使 API 再次失败,并出现相同的错误“403 服务帐户无法在没有域范围授权的情况下邀请与会者”。为服务帐户提供“域范围验证”是不够的。
  • 哎呀兄弟。这解决了我的问题。第 2 步至关重要,而且记录不充分。
  • 如果我没有 G Suite 帐户怎么办?
【解决方案2】:

向服务帐户授予域范围权限的目的是让这些帐户能够代表域中的用户访问数据。

如果您授予它域范围的权限但没有“模拟”任何帐户,则服务帐户的行为就像您没有授予此权限一样:它正在尝试访问自己的日历。

当服务帐户模拟域中的另一个用户时(即,当它代表用户行事时),服务帐户可以访问该用户可以访问的资源。

要模拟其他用户,您必须指定用户的电子邮件地址。 就我而言,我使用 Node.JS 库,我的模拟代码如下所示:

const auth = new google.auth.JWT(
  config.client_email,
  null,
  config.private_key,
  ["https://www.googleapis.com/auth/calendar.events"],
  "!!! user email to impersonate !!!!",
);

更重要的是,如果您需要填写参加者[]数组,您必须授权服务帐户发送电子邮件。因为你得到了未经授权的错误。

为此,您需要在 G Suite 域的管理控制台上添加 https://www.googleapis.com/auth/gmail.send 范围。

您可以在这里找到更多信息:https://issuetracker.google.com/issues/14170493

【讨论】:

    【解决方案3】:

    仅供参考

    在我的情况下,在 Node.js 上,我遵循了 @Anathorn 的指示,但我不断得到

    服务帐户无法在没有全域授权的情况下邀请与会者

    然后我在我的身份验证行中添加了我应该替换的电子邮件,并且它起作用了。

    const auth = new google.auth.JWT(
        CREDENTIALS.client_email,`
        null,
        CREDENTIALS.private_key,
        SCOPES,
        "admin@domain.com",
        "12345678987654321"
    );
    

    【讨论】:

      【解决方案4】:

      对于使用 googleapis-nodejs-client 库的用户,我们在 a issue in the google-auth-library-nodejs github page 上提供了解决方案。

      从@Anathorn 执行所有配置步骤并以这种方式记录服务帐户对我有用:

      const auth = new google.auth.GoogleAuth({
      keyFile: './service.json',
      scopes: [
        'https://www.googleapis.com/auth/calendar',
        'https://www.googleapis.com/auth/calendar.events'
      ],
      clientOptions: {
        subject: 'email@email.com'
      },
      

      });

      编辑: 它只能在本地工作!

      据我所知,在具有域范围权限的 GCP(对我来说是云功能)上运行时,您不能使用应用默认凭据,只有使用带有 JWT 的身份验证才能工作。

      【讨论】:

        【解决方案5】:

        对于可能遇到此问题的其他任何人,对我来说,这是 Anathorn 的回答和 Maksym Kalin 的回答的结合。这是因为我没有冒充用户的电子邮件地址。

        一个用户之前尝试过提交你正在使用的同一个库(我也在使用它),但是被 repo 所有者拒绝了(多么悲伤)

        https://github.com/spatie/laravel-google-calendar/pull/97

        无论如何,他的代码是我最终修复它的方法。

        祝其他遇到此问题的人好运,这让我很痛苦太久了。

        【讨论】:

        • 我已经在这篇文章中完成了所有的测试,但是当我尝试这样与与会者一起创建一个日历事件时,我遇到了这个错误:{“error”:“unauthorized_client”,“error_description”:“客户端是未经授权使用此方法检索访问令牌,或客户端未授权任何请求的范围。” } 你有什么想法吗?