Google API OAuth2, Service Account, “error” : “invalid_grant”

后端 未结 3 1148
离开以前
离开以前 2020-12-04 01:48

I\'m trying to use service account to sync calendars from Dynamics CRM software to Google. During this I faced lack of documentation on google API for .net, especially regar

3条回答
  •  醉梦人生
    2020-12-04 02:03

    After some investigations I found, that Google API does not work as expected with your personal account @gmail.com. You should have organization domain account in Google in format you@your_organisation_domain

    Then, what is also pretty confusing, there is documentation at Google Drive API page, with "Delegate domain-wide authority to your service account" section not mentioned at Calendar API page. There are 7 steps in the section, are required to be done.

    BTW with personal account administration site admin.google.com is even unavailable. So it's impossible to perform these 7 steps with @gmail.com account.

    Then, when client is authorised in Google Apps Admin Console > Security > Advanced settings > Manage OAuth Client access the code starts to work.

    There is a code that works for me:

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Security.Cryptography.X509Certificates;
    using Google.Apis.Calendar.v3;
    using Google.Apis.Calendar.v3.Data;
    using Google.Apis.Auth.OAuth2;
    using Google.Apis.Services;
    
    namespace CrmToGoogleCalendar
    {
        class Program
        {
    
            static void Connect()
            {
                Console.WriteLine("Calendar via OAuth2 Service Account Sample");
    
                var certificate = new X509Certificate2("My MC Project-3f38defdf4e4.p12", "notasecret", X509KeyStorageFlags.Exportable);
                var serviceAccountEmail = "795039984093-c6ab1mknpediih2eo9cb70mc9jpu9h03@developer.gserviceaccount.com";
                var userAccountEmail = "me@testdomain.com"; 
                var credential = new ServiceAccountCredential(new ServiceAccountCredential.Initializer(serviceAccountEmail) 
                    {
                        User = userAccountEmail,
                        Scopes = new[] { CalendarService.Scope.Calendar }
                    }
                    .FromCertificate(certificate));
    
                var service = new CalendarService(new BaseClientService.Initializer()
                {
                    ApplicationName = "Test calendar sync app",
                    HttpClientInitializer = credential
    
                });
    
                /* Get list of calendars */
                var calList = service.CalendarList.List().Execute().Items;
                var myCalendar = calList.First(@c => @c.Id == userAccountEmail);
    
                /* CREATE EVENT */
                var event1 = new Event()
                    {
                        Kind = "calendar#event",
                        Summary = "Calendar event via API",
                        Description = "Programmatically created",
                        Status = "confirmed",
                        Organizer = new Event.OrganizerData() {
                            Email = userAccountEmail
                        },
                        Start = new EventDateTime()
                            {
                                DateTime = DateTime.Now.AddDays(1)
                            },
                        End = new EventDateTime()
                        {
                            DateTime = DateTime.Now.AddDays(1).AddHours(1)
                        },
                        ColorId = "6",
                        Reminders = new Event.RemindersData()
                            {
                                UseDefault = false,
                                Overrides = new List(
                                    new [] {
                                        new EventReminder()
                                            {
                                                Method = "popup",
                                                Minutes = 60
                                            }
                                    })
                            }
                    };
    
                event1 = service.Events.Insert(event1, myCalendar.Id).Execute();
                Console.WriteLine("Created event Id: {0}", event1.Id);
    
    
                /* ENLIST EVENTS */
                Console.WriteLine("calendar id={0}", myCalendar.Id);
                var events = service.Events.List(myCalendar.Id).Execute();
                foreach (var @event in events.Items)
                {
                    Console.WriteLine("Event ID: {0}, ICalUID: {1}", @event.Id, @event.ICalUID);
                    Console.WriteLine("  Name: {0}", @event.Summary);
                    Console.WriteLine("  Description: {0}", @event.Description);
                    Console.WriteLine("  Status: {0}", @event.Status);
                    Console.WriteLine("  Color: {0}", @event.ColorId);
                    Console.WriteLine("  Attendees: {0}", @event.Attendees == null ? "" : @event.Attendees.Select(a => a.Email).ToString());
                    Console.WriteLine("  Kind: {0}", @event.Kind);
                    Console.WriteLine("  Location: {0}", @event.Location);
                    Console.WriteLine("  Organizer: {0}", @event.Organizer.Email);
                    Console.WriteLine("  Recurrence: {0}", @event.Recurrence == null ? "no recurrence" : String.Join(",", @event.Recurrence));
                    Console.WriteLine("  Start: {0}", @event.Start.DateTime == null ? @event.Start.Date : @event.Start.DateTime.ToString());
                    Console.WriteLine("  End: {0}", @event.End.DateTime == null ? @event.End.Date : @event.End.DateTime.ToString());
                    Console.WriteLine("  Reminders: {0}", @event.Reminders.UseDefault.Value ? "Default" : "Not defailt, " + 
                        (@event.Reminders.Overrides == null ? "no overrides" : String.Join(",", @event.Reminders.Overrides.Select(reminder => reminder.Method + ":" + reminder.Minutes)))
                        );
                    Console.WriteLine("=====================");
                }
    
                Console.ReadKey();
            }
    
    
            static void Main(string[] args)
            {
                Connect();
            }
        }
    }
    

    The output produced looks so:

    Calendar via OAuth2 Service Account Sample
    Created event Id: jkits4dnpq6oflf99mfqf1kdo0
    calendar id=me@testdomain.com
    Event ID: 1logvocs77jierahutgv962sus, ICalUID: 1logvocs77jierahutgv962sus@google.com
      Name: test event
      Description: test description2
      Status: confirmed
      Color: 
      Attendees: 
      Kind: calendar#event
      Location: location2
      Organizer: me@testdomain.com
      Recurrence: RRULE:FREQ=WEEKLY;BYDAY=TH
      Start: 2014-07-31
      End: 2014-08-01
      Reminders: Not defailt, email:10,popup:10
    =====================
    Event ID: 1logvocs77jierahutgv962sus_20140814, ICalUID: 1logvocs77jierahutgv962sus@google.com
      Name: test event updated
      Description: test description2
      Status: confirmed
      Color: 
      Attendees: 
      Kind: calendar#event
      Location: location2
      Organizer: me@testdomain.com
      Recurrence: no recurrence
      Start: 2014-08-14
      End: 2014-08-15
      Reminders: Not defailt, email:10
    =====================
    Event ID: 974hqdhh8jhv5sdobkggmdvvd8, ICalUID: 974hqdhh8jhv5sdobkggmdvvd8@google.com
      Name: One hour event
      Description: test description
      Status: confirmed
      Color: 7
      Attendees: 
      Kind: calendar#event
      Location: Meeting Room Hire, Broadway, 255 The Bdwy, Broadway, NSW 2007, Australia
      Organizer: me@testdomain.com
      Recurrence: no recurrence
      Start: 1/08/2014 10:00:00 AM
      End: 1/08/2014 11:00:00 AM
      Reminders: Default
    =====================
    Event ID: jkits4dnpq6oflf99mfqf1kdo0, ICalUID: jkits4dnpq6oflf99mfqf1kdo0@google.com
      Name: Calendar event via API
      Description: Programmatically created
      Status: confirmed
      Color: 6
      Attendees: 
      Kind: calendar#event
      Location: 
      Organizer: me@testdomain.com
      Recurrence: no recurrence
      Start: 2/08/2014 12:30:50 PM
      End: 2/08/2014 1:30:50 PM
      Reminders: Not defailt, popup:60
    =====================
    

    First event is recurrent weekly whole day event series. Second is updated single event of the first (has the same UID). Third is single event for one hour. The last is created by code above.

    Hope this will help others to economy their time.

提交回复
热议问题