且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

谷歌日历 API.向某人日历添加事件会引发错误“错误 401:invalid_client";就在认证时

更新时间:2023-12-04 13:05:34

答案:

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

更多信息:

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

>

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

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

OAuth2:

OAuth2 是一个特定的授权框架.该框架在

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

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

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

范围:

在单个 API 中可以有多个访问范围 - 对日历事件具有只读访问权限与对用户拥有的所有日历具有完全读写访问权限大不相同.这就是示波器发挥作用的地方.

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

在对用户授权进行初始请求之前,在应用程序本身中定义了范围.例如,在 C# 中(取自 .NET Calendar API Quickstart)::>

//作用域被定义为一个字符串数组:静态字符串 [] 范围 = { CalendarService.Scope.CalendarReadonly };...UserCredential 凭证;凭据 = GoogleWebAuthorizationBroker.AuthorizeAsync(GoogleClientSecrets.Load(stream).Secrets,范围,用户",CancellationToken.None,新的 FileDataStore(credPath, true)).Result;

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

服务帐户:

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

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

通常,您希望为其执行任务或访问资源的每个用户都需要为您的应用程序提供明确的权限.但是,对于 G Suite 域,您可以使用带有 域的服务帐户-广泛授权代表用户完成任务,无需要求.

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

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

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

参考:


相关问题:

I have a C# class library from which I am trying to add an event to someone calendar just by using his/her email address and password as credentials. So I debug it and once started a new page in the internet browser is open and below error is displayed:

Below the code:

// 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",
   });

Why this error is happening? ClientId is not the gmail account? Also why a new page in internet browser is opened? I want to do authentication without opening a page in the internet browser because this class library is called from a windows service so I need authentication to be done in the background.

Answer:

In order to insert methods into a user's Calendar, you need the user to give your application permission to make actions on their behalf. This is done using a Google Cloud Platform (GCP) Project, with OAuth2 Authentication.

More Information:

Each application which runs and takes actions on behalf of a Google account user has to have the scope of its ability well defined so that it can't start doing things that a user hasn't given it permission to do.

For example: if you give an application permission to create Calendar events, you don't want it to be able to do other things such as read your emails or download the contents of your Drive.

In order to designate what your application has the power to do, it needs to be registered with Google. As you have already deduced in your question and comments, the Client ID and Client Secret required by an application connecting to a G Suite API isn't simply the username and password of a Google Account, but a designated ID-secret ID pair which is provided by Google to identify your application.

OAuth2:

OAuth2 is a specific authorisation framework. The framework is defined in RFC 6749 and sets out the process in which a user can authorise an application to access their account. The limit of the authorisation is defined by the scope of the application on authorisation, and can not be changed without explicit re-authorisation by the user.

Before continuing it's worth defining a few important terms here:

User:

A user is the person; the individual that has an account and gives permission for an application to take actions on their behalf.

Client or Application:

A Client or Application is a program which is designed to take actions over HTTP by connecting to a service's API. Applications can be mobile apps, web apps or desktop clients.

Authorisation Server:

An Authorisation server is a server which is separate from the servers that store user resources. It verfies the user's identity and provides a grant which can be used to get an access token to a resource server.

Resource Server:

This is the server where user data is stored. This could be anything from user information to files or emails.

The authorisation flow has already been well documented, but for the sake of this scenario we can abstract it down to the following steps:

  • An Application wishes to take an action on a resource server on behalf of a user.
  • The Application makes an authorisation request to the user. This is generally presented as a login page for the account for which the application is accessing.
  • The user logs in to their account and is presented with an OAuth consent screen - this contains information such as the application's name, and the list of tasks that it is requesting authorisation for. These are often generic, and will say something like See and download all your Google Drive files or View and edit events on all your calendars. This allows the user to know what they are authorising before they confirm.
  • An Authorisation Grant is given to the application.
  • The Application provides the obtained authorisation grant along with its assigned client credentials to an authorisation server.
  • On verifying that both the user's grant and the client's credentials are correct, the authorisation server returns an access token which can be used to access the requested and approved resources. Note: This is normally all handled by your client library for whichever language you use.
  • The Application can now make a request to the resource server, providing the access token obtained from the authorisation flow. It is at this point that the permitted resources can be accessed.

Google Cloud Platform Projects:

A GCP project what Google sees as your application. The registration for your application is required to be able to obtain the client ID and client secret which your application will need in order to get an access token in the authorisation flow. In the GCP console you can set up all the required services that your application needs. Each API you wish to use has to be enabled for your application, as there are many Google services with APIs and they are disabled by default.

Once a GCP Project has been created, you can use the API Library (From the ≡ > APIs & Services > Library menu item on the left) to find and enable the API. Note that for your use case you will want to enable the Google Calendar API and not the CalDAV API.

You will also need to set up a consent screen before obtaining credentials for your application. An OAuth consent screen is what your users will be presented with in the first step of the OAuth flow:

When setting up your OAuth consent screen, you will need to provide the following information:

  • Application type (public or internal to your domain)
  • Application name
  • The scopes that your application needs (explained in the next section)

After the consent screen has been set up, you can download the client credentials for your application. With these, your application has permission to run as a client, but each user that has their resources accessed will still have to give their explicit permission to allow the application to do so.

Scopes:

Within a single API there can be many scopes of access - having read-only access to calendar events is vastly different to having complete read-write access to all calendars that a user owns. This is where scopes come into play.

A scope is defined as its namesake; that is to say, a scope defines the scope of access an application has to a service. Even though an entire API has been enabled for a project doesn't mean that you need to use all features of the API. For this reason, scopes need to be defined.

Scopes are defined in the application itself before making the initial request for the user grant. In C#, for example (taken from the .NET Calendar API Quickstart):

// scopes are defined as an array of strings:
static string[] Scopes = { CalendarService.Scope.CalendarReadonly };
...
UserCredential credential;
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
                    GoogleClientSecrets.Load(stream).Secrets,
                    Scopes,
                    "user",
                    CancellationToken.None,
                    new FileDataStore(credPath, true)).Result;

The access token that is stored is based on the scopes that were defined in the call. If a method is called which needs a different scope to those which the token grants access to, the call will fail with a 403: Unauthorized error. The required scope will need to be added to the application, the old access token deleted and the user will need to grant permission for the new scopes.

Service Accounts:

As well as regular users, there is another special type of Google account called a Service Account. From the documentation:

A service account is a special kind of account used by an application or a virtual machine (VM) instance, not a person. Applications use service accounts to make authorized API calls.

Normally, every user for whom you wish to perform tasks or access resources needs to give explicit permission for your application to do so. For G Suite domains, however, you can use a service account with domain-wide delegation to complete tasks on behalf of users without the requirement.

Service accounts use a special kind of service-account credential which can be created in GCP and used in your application. Rather than making a UserCredential object, a ServiceAccountCredential is needed which doesn't require involvment by an end user.

When running a service account on behalf of a user with domain-wide delegation, the name of the user needs to be specified in the delegated credentials so the application knows which user in the domain to run as. If a user is not provided, the service account will run the code as itself; which is useful in some cases but often times will not return an error and so it may not be clear for whom the operation was run.

Note: While Service Accounts can be created by anyone, domain-wide delegation of authority can only be accomplished for a G Suite domain, and not @gmail.com addresses. All Gmail account users must give explicit permission for an application to run on thier behalf as set out by the OAuth flow.

References:


Related Questions: