当前位置: 首页 > 知识库问答 >
问题:

谷歌日历API v3。使用服务帐户或Web应用程序ID进行NET身份验证

慕承恩
2023-03-14

我需要在我的上连接谷歌日历。NET 4.5应用程序(VS 2013项目)。我想从日历中获取所有信息,例如:事件、日期、笔记、姓名、客人等。。。

我使用Google开发者控制台创建了一个Web应用程序客户端ID和一个服务帐户,但我得到了不同的错误,没有结果。我实现了两种不同的方法,一种是使用Web应用程序客户端ID登录,另一种是使用服务帐户。

这是常见的ASPX页面

public partial class Calendar : System.Web.UI.Page
{
    // client_secrets.json path.
    private readonly string GoogleOAuth2JsonPath = ConfigurationManager.AppSettings["GoogleOAuth2JsonPath"];

    // p12 certificate path.
    private readonly string GoogleOAuth2CertificatePath = ConfigurationManager.AppSettings["GoogleOAuth2CertificatePath"];

    // @developer... e-mail address.
    private readonly string GoogleOAuth2EmailAddress = ConfigurationManager.AppSettings["GoogleOAuth2EmailAddress"];

    // certificate password ("notasecret").
    private readonly string GoogleOAuth2PrivateKey = ConfigurationManager.AppSettings["GoogleOAuth2PrivateKey"];

    // my Google account e-mail address.
    private readonly string GoogleAccount = ConfigurationManager.AppSettings["GoogleAccount"]; 

    protected void Page_Load(object sender, EventArgs e)
    {
        // Enabled one at a time to test
        //GoogleLoginWithServiceAccount();
        GoogleLoginWithWebApplicationClientId();
    }
}

使用Web应用程序客户端ID

我尝试为JSON配置文件配置重定向URI参数,但URI似乎不起作用。我在开发环境中,所以我在端口44300上使用IIS Express(启用SSL)。我得到的错误是:

Error: redirect_uri_mismatch
Application: CalendarTest
The redirect URI in the request: http://localhost:56549/authorize/ did not match a registered redirect URI.
Request details
scope=https://www.googleapis.com/auth/calendar
response_type=code
redirect_uri=http://localhost:56549/authorize/
access_type=offline
client_id=....apps.googleusercontent

代码

private void GoogleLoginWithWebApplicationClientId()
{
    UserCredential credential;

    // This example uses the client_secrets.json file for authorization.
    // This file can be downloaded from the Google Developers Console
    // project.
    using (FileStream json = new FileStream(Server.MapPath(GoogleOAuth2JsonPath), FileMode.Open,
        FileAccess.Read))
    {
        credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
            GoogleClientSecrets.Load(json).Secrets,
            new[] { CalendarService.Scope.Calendar },
            "...@developer.gserviceaccount.com", CancellationToken.None,
            new FileDataStore("Calendar.Auth.Store")).Result;
    }

    // Create the service.
    CalendarService service = new CalendarService(new BaseClientService.Initializer()
    {
        HttpClientInitializer = credential,
        ApplicationName = "CalendarTest"
    });

    try
    {
        CalendarListResource.ListRequest listRequest = service.CalendarList.List();
        IList<CalendarListEntry> calendarList = listRequest.Execute().Items;

        foreach (CalendarListEntry entry in calendarList)
        {
            txtCalendarList.Text += "[" + entry.Summary + ". Location: " + entry.Location + ", TimeZone: " +
                                    entry.TimeZone + "] ";
        }
    }
    catch (TokenResponseException tre)
    {
        txtCalendarList.Text = tre.Message;
    }
}

使用服务帐户(首选)

我可以到达CalendarListResources。ListRequest listRequest=service。CalendarList。List();行,所以我猜登录可以工作,但是,当我想要IList上的列表时

Error:"unauthorized_client", Description:"Unauthorized client or scope in request.", Uri:""

代码

private void GoogleLoginWithServiceAccount()
{
    /*
     * From https://developers.google.com/console/help/new/?hl=en_US#generatingoauth2:
     * The name of the downloaded private key is the key's thumbprint. When inspecting the key on your computer, or using the key in your application,
     * you need to provide the password "notasecret".
     * Note that while the password for all Google-issued private keys is the same (notasecret), each key is cryptographically unique.
     * GoogleOAuth2PrivateKey = "notasecret".
     */
    X509Certificate2 certificate = new X509Certificate2(Server.MapPath(GoogleOAuth2CertificatePath),
        GoogleOAuth2PrivateKey, X509KeyStorageFlags.Exportable);

    ServiceAccountCredential credential = new ServiceAccountCredential(
        new ServiceAccountCredential.Initializer(GoogleOAuth2EmailAddress)
        {
            User = GoogleAccount,
            Scopes = new[] { CalendarService.Scope.Calendar }
        }.FromCertificate(certificate));

    // Create the service.
    CalendarService service = new CalendarService(new BaseClientService.Initializer()
    {
        HttpClientInitializer = credential,
        ApplicationName = "CalendarTest"
    });

    try
    {
        CalendarListResource.ListRequest listRequest = service.CalendarList.List();
        IList<CalendarListEntry> calendarList = listRequest.Execute().Items;

        foreach (CalendarListEntry entry in calendarList)
        {
            txtCalendarList.Text += "[" + entry.Summary + ". Location: " + entry.Location + ", TimeZone: " +
                                    entry.TimeZone + "] ";
        }
    }
    catch (TokenResponseException tre)
    {
        txtCalendarList.Text = tre.Message;
    }
}

我更喜欢服务帐户登录,因为用户无需使用同意屏幕登录,因为应用程序应该在每次需要刷新时自行完成。是否可以使用免费谷歌帐户的服务帐户,或者我需要管理控制台?我读过很多关于这个的相互矛盾的报道。。。

无论如何,在Google和StackOverflow中四处寻找,我没有找到解决方案。我看到并尝试了许多问题和解决方案,但没有结果。一些例子:

  • 不断得到错误:redirect_uri_mismatch使用youtube api v3
  • 谷歌日历redirect_uri_mismatch
  • 使用Asp. Net MVC通过服务帐户插入Google API Calender v3事件
  • https://developers.google.com/google-apps/calendar/instantiate
  • https://groups.google.com/forum/#!主题/google-calent-api/MySzyAXq12Q

请帮忙!:-)

更新1-使用服务帐户(首选)-已解决!

我的代码中唯一的问题是:

ServiceAccountCredential credential = new ServiceAccountCredential(
    new ServiceAccountCredential.Initializer(GoogleOAuth2EmailAddress)
    {
        //User = GoogleAccount,
        Scopes = new[] { CalendarService.Scope.Calendar }
    }.FromCertificate(certificate));

不需要用户=GoogleAccount。


共有1个答案

安明亮
2023-03-14

您的身份验证肯定有问题。这是我的服务帐户身份验证方法的副本。

 /// <summary>
        /// Authenticating to Google using a Service account
        /// Documentation: https://developers.google.com/accounts/docs/OAuth2#serviceaccount
        /// </summary>
        /// <param name="serviceAccountEmail">From Google Developer console https://console.developers.google.com</param>
        /// <param name="keyFilePath">Location of the Service account key file downloaded from Google Developer console https://console.developers.google.com</param>
        /// <returns></returns>
        public static CalendarService AuthenticateServiceAccount(string serviceAccountEmail, string keyFilePath)
        {

            // check the file exists
            if (!File.Exists(keyFilePath))
            {
                Console.WriteLine("An Error occurred - Key file does not exist");
                return null;
            }

            string[] scopes = new string[] {
        CalendarService.Scope.Calendar  ,  // Manage your calendars
        CalendarService.Scope.CalendarReadonly    // View your Calendars
            };

            var certificate = new X509Certificate2(keyFilePath, "notasecret", X509KeyStorageFlags.Exportable);
            try
            {
                ServiceAccountCredential credential = new ServiceAccountCredential(
                    new ServiceAccountCredential.Initializer(serviceAccountEmail)
                    {
                        Scopes = scopes
                    }.FromCertificate(certificate));

                // Create the service.
                CalendarService service = new CalendarService(new BaseClientService.Initializer()
                {
                    HttpClientInitializer = credential,
                    ApplicationName = "Calendar API Sample",
                });
                return service;
            }
            catch (Exception ex)
            {

                Console.WriteLine(ex.InnerException);
                return null;

            }
        }

我也有一个教程。我的教程Google Calendar API身份验证与C#上面的代码直接从我在GitHub上的示例项目Google-Dotnet-Samples项目中摘录

注意:记住,服务帐户不是你的。它现在有任何日历,当您开始时,您需要创建一个日历并将其插入日历列表中,然后才能返回任何结果。此外,由于您无法以服务帐户登录,您将无法通过Google日历的web版本查看此日历。最好的解决方法是让服务帐户授予您对日历的权限。

 类似资料:
  • 我正在努力解决这个问题:我正在尝试使用一个服务帐户,从PHP脚本在Google日历中创建一个事件。 以下是我所做的: 创建了一个Google Cloud Project 启用日历API 创建了一个OAuth 2.0服务帐户,其中包含客户端ID、电子邮件地址和公钥 下载了密钥文件并将其保存在我的网站中 使用服务帐户中创建的电子邮件地址共享我的日历(具有管理共享权限) 这是我的代码: 我已经尽可能地调

  • 我正在使用Google. net客户端库来访问谷歌日历应用编程接口。我需要研发创建日历事件并将其发布给用户的应用程序。 这是一个服务器到服务器的应用程序,所以我创建了一个服务帐户,并用它来发送邀请。当从web浏览器提交响应时,创建的与会者对这些事件的响应将被更新,但当来自outlook等任何邮件客户端的响应时,响应将以电子邮件的形式发送给服务帐户电子邮件id(这是一个虚拟电子邮件id)。如何将有效

  • 我正在更新一个Web服务应用程序,该应用程序调用Google的日历API来列出特定日历的日历事件并插入新的日历事件。我正在尝试将其升级到api的版本3。对于身份验证,我使用我在Google Developers Console(https://console.developers.google.com)中创建的服务帐户凭据。我可以使用以下代码创建CalendarService: 但是当我调用lis

  • 在我的ASP。NET核心3应用程序,我想实现与谷歌登录,只允许特定用户的身份验证。 到目前为止,我所做的是遵循以下教程: https://docs.microsoft.com/en-us/aspnet/core/security/authentication/social/social-without-identity?view=aspnetcore-3.0 https://docs.micros

  • 目前,Google Assitant包括一种简单的方法来请求有关用户的不可识别信息,以及通过OAuth2在第三方服务上对用户进行身份验证的详细流程。如果我只需要让用户在 Google 上进行身份验证,该怎么办?我尝试使用Google OAuth2信息填写帐户链接流程,但这似乎不起作用。如果最后一件事应该流利地工作,那么这将是一个足够的答案。 上下文:用户已经只在相关网页上使用谷歌进行身份验证。我所