谷歌日历 API。向某人日历添加事件在身份验证时会引发错误“错误 401:invalid_client”

use*_*552 1 c# google-calendar-api oauth-2.0 google-oauth visual-studio-2013

我有一个 C# 类库,我试图通过使用他/她的电子邮件地址和密码作为凭据来将事件添加到某人的日历中。所以我对其进行调试,一旦启动,互联网浏览器中就会打开一个新页面,并显示以下错误:

在此输入图像描述

代码如下:

// It crashes when calling GoogleWebAuthorizationBroker.AuthorizeAsync
UserCredential credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
                new ClientSecrets
                {
                    ClientId = "myGoogleAccount@gmail.com",
                    ClientSecret = "myGoogleAccountPasswordHere",
                },
                new[] { CalendarService.Scope.Calendar },
                System.Environment.UserName,
                CancellationToken.None).Result;

   // Create the service.
   var service = new CalendarService(new BaseClientService.Initializer()
   {
                HttpClientInitializer = credential,
                ApplicationName = "Calendar API Sample",
   });
Run Code Online (Sandbox Code Playgroud)

为什么会发生这个错误?ClientId不是gmail帐户吗?另外为什么互联网浏览器中会打开一个新页面?我想在不打开互联网浏览器页面的情况下进行身份验证,因为这个类库是从 Windows 服务调用的,所以我需要在后台完成身份验证。

Raf*_*rmo 5

回答:

\n

为了将方法插入用户的日历中,您需要用户授予您的应用程序代表他们执行操作的权限。这是使用 Google Cloud Platform (GCP) 项目和 OAuth2 身份验证完成的。

\n

更多信息:

\n

每个代表 Google 帐户用户运行并采取操作的应用程序都必须明确定义其能力范围,以便它无法开始执行用户未授予其执行权限的操作。

\n

例如:如果您授予应用程序创建日历事件的权限,您不希望它能够执行其他操作,例如读取电子邮件或下载云端硬盘的内容。

\n

为了指定您的应用程序有权执行的操作,它需要向 Google 注册。正如您在问题和评论中已经推断出的那样,连接到 G Suite API 的应用程序所需的客户端 ID 和客户端密钥不仅仅是 Google 帐户的用户名和密码,而是指定的 ID-密钥 ID 对,由 Google 提供,用于识别您的应用程序。

\n

OAuth2:

\n

OAuth2是一个特定的授权框架。该框架在RFC 6749中定义,并规定了用户授权应用程序访问其帐户的流程。授权的限制由授权应用的范围决定,未经用户明确重新授权,不得更改。

\n

在继续之前,有必要在这里定义一些重要术语:

\n

用户:

\n
\n

用户就是人;拥有帐户并允许应用程序代表其采取行动的个人。

\n
\n

客户或应用程序:

\n
\n

客户端或应用程序是一个程序,旨在通过连接到服务的 API 通过 HTTP 执行操作。应用程序可以是移动应用程序、Web 应用程序或桌面客户端。

\n
\n

授权服务器:

\n
\n

授权服务器是与存储用户资源的服务器分开的服务器。它验证用户的身份并提供可用于获取资源服务器访问令牌的授权。

\n
\n

资源服务器:

\n
\n

这是存储用户数据的服务器。这可以是从用户信息到文件或电子邮件的任何内容。

\n
\n

授权流程已经有详细记录,但对于这种情况,我们可以将其抽象为以下步骤:

\n
    \n
  • 应用程序希望代表用户在资源服务器上执行操作。
  • \n
  • 应用程序向用户发出授权请求。这通常显示为应用程序正在访问的帐户的登录页面。
  • \n
  • 用户登录其帐户后会看到一个 OAuth 同意屏幕 - 其中包含应用程序名称及其请求授权的任务列表等信息。这些通常是通用的,并且会说类似See and download all your Google Drive files或 的内容View and edit events on all your calendars。这使得用户可以在确认之前知道他们正在授权什么。
  • \n
  • 向该申请授予授权。
  • \n
  • 应用程序将获得的授权许可及其分配的客户端凭证提供给授权服务器。
  • \n
  • 在验证用户的授权和客户端的凭据是否正确后,授权服务器返回一个访问令牌,该令牌可用于访问请求和批准的资源。注意:无论您使用哪种语言,这通常都由您的客户端库处理
  • \n
  • 应用程序现在可以向资源服务器发出请求,提供从授权流程中获得的访问令牌。此时就可以访问允许的资源。
  • \n
\n

谷歌云平台项目:

\n

一个 GCP 项目,Google 将其视为您的应用程序。您的应用程序需要注册才能获取您的应用程序需要的客户端 ID 和客户端密钥,以便在授权流程中获取访问令牌。\n在GCP 控制台中,您可以设置您的应用程序所需的所有服务。应用需求。您希望使用的每个 API 都必须为您的应用程序启用,因为有许多带有 API 的 Google 服务,并且默认情况下它们是禁用的。

\n

创建 GCP 项目后,您可以使用 API 库(从\xe2\x89\xa1 > APIs & Services > Library左侧的菜单项)查找并启用 API。请注意,对于您的用例,您将需要启用 Google Calendar API 而不是 CalDAV API。

\n

在获取应用程序的凭据之前,您还需要设置同意屏幕。OAuth 同意屏幕是您的用户在 OAuth 流程的第一步中将看到的内容:

\n

在此输入图像描述

\n

设置 OAuth 同意屏幕时,您需要提供以下信息:

\n
    \n
  • 应用程序类型(您的域的公共或内部)
  • \n
  • 应用名称
  • \n
  • 您的应用程序需要的范围(在下一节中解释)
  • \n
\n

设置同意屏幕后,您可以下载应用程序的客户端凭据。有了这些,您的应用程序就有权作为客户端运行,但每个访问其资源的用户仍然必须给予明确的许可才能允许应用程序这样做。

\n

适用范围:

\n

在单个 API 中,可以有多个访问范围 - 对日历事件进行只读访问与对用户拥有的所有日历进行完全读写访问有很大不同。这就是作用域发挥作用的地方。

\n

范围的定义与其同名;也就是说,范围定义了应用程序对服务的访问范围。即使项目启用了整个 API,并不意味着您需要使用该 API 的所有功能。因此,需要定义范围。

\n

在发出用户授权的初始请求之前,范围是在应用程序本身中定义的。例如,在 C# 中(取自.NET Calendar API 快速入门):

\n
// scopes are defined as an array of strings:\nstatic string[] Scopes = { CalendarService.Scope.CalendarReadonly };\n...\nUserCredential credential;\ncredential = GoogleWebAuthorizationBroker.AuthorizeAsync(\n                    GoogleClientSecrets.Load(stream).Secrets,\n                    Scopes,\n                    "user",\n                    CancellationToken.None,\n                    new FileDataStore(credPath, true)).Result;\n
Run Code Online (Sandbox Code Playgroud)\n

存储的访问令牌基于调用中定义的范围。如果调用的方法需要与令牌授予访问权限的范围不同的范围,则调用将失败并出现错误403: Unauthorized。需要将所需的范围添加到应用程序中,删除旧的访问令牌,并且用户需要授予新范围的权限。

\n

服务帐户:

\n

除了普通用户之外,还有另一种特殊类型的 Google 帐户,称为服务帐户。从文档中:

\n
\n

服务帐户是应用程序或虚拟机 (VM) 实例(而不是个人)使用的一种特殊帐户。应用程序使用服务帐户进行授权的 API 调用。

\n
\n

通常,您希望为其执行任务或访问资源的每个用户都需要明确授予您的应用程序这样做的权限。但是,对于 G Suite 域,您可以使用具有域范围委派的服务帐户来代表用户完成任务,而无需这样做。

\n

服务帐户使用一种特殊类型的服务帐户凭据,可以在 GCP 中创建并在您的应用程序中使用。不需要创建一个UserCredential对象,而是ServiceAccountCredential需要一个不需要最终用户参与的对象

\n

当使用域范围委派代表用户运行服务帐户时,需要在委派凭据中指定用户名,以便应用程序知道要以域中的哪个用户身份运行。如果未提供用户,服务帐户将自行运行代码;这在某些情况下很有用,但通常不会返回错误,因此可能不清楚该操作是为谁运行的。

\n

注意:虽然任何人都可以创建服务帐户,但只能针对 G Suite 域而不是地址完成域范围的授权@gmail.com。所有 Gmail 帐户用户都必须按照 OAuth 流程的规定明确授予应用程序代表他们运行的权限。

\n

参考:

\n\n
\n

相关问题:

\n\n