![](/img/trans.png)
[英]Issues with Google OAuth2 in iOS - “invalid_grant” error
[英]Google API OAuth2, Service Account, “error” : “invalid_grant”
我正在嘗試使用服務帳戶將Dynamics CRM軟件的日歷同步到Google。 在此過程中,我遇到了關於.net的谷歌API缺乏文檔,特別是關於授權。 由於使用了過時的庫和類,大多數Google樣本都無法編譯。
所以我發現了一些關於實習和接收錯誤的例子。 有人可以看看我的樣品,告訴我做錯了什么?
准備步驟:
然后創建了控制台應用程序並設法安裝OAuth和Calendar nuget包。 有:
有一個代碼可以找到並適應我的需求:
using System;
using System.Security.Cryptography.X509Certificates;
using Google.Apis.Calendar.v3;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Services;
namespace CrmToGoogleCalendar
{
class Program
{
static void Connect()
{
var certificate = new X509Certificate2("My Project-ee7facaa2bb1.p12", "notasecret", X509KeyStorageFlags.Exportable);
var serviceAccountEmail = "506310960175-q2k8hjl141bml57ikufinsh6n8qiu93b@developer.gserviceaccount.com";
var userAccountEmail = "<my email>@gmail.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
});
var calList = service.CalendarList.List().Execute().Items;
foreach (var cal in calList)
{
Console.WriteLine(cal.Id);
}
}
static void Main(string[] args)
{
Connect();
}
}
}
我在應用和Fiddler中看到的與Google API的通信是:
要求:
主持人:HTTPS accounts.google.com,網址:/ o / oauth2 / token
斷言:長二進制字符串
grant_type:urn:ietf:params:oauth:grant-type:jwt-bearer
響應:
HTTP / 1.1 400錯誤請求內容類型:application / json Cache-Control:no-cache,no-store,max-age = 0,must-revalidate Pragma:no-cache Expires:Fri,01 Jan 01 00:00: 00 GMT日期:星期四,2014年7月24日06:12:18 GMT X-Content-Type-Options:nosniff X-Frame-Options:SAMEORIGIN X-XSS-Protection:1; mode = block服務器:GSE Alternate-Protocol:443:quic Transfer-Encoding:chunked
1f {“error”:“invalid_grant”} 0
請提前幫助和感謝!
經過一些調查后發現,Google API無法按預期使用您的個人帳戶@ gmail.com。 您應該以Google @ your_organisation_domain格式在Google中擁有組織域帳戶
然后,同樣令人困惑的是, Google Drive API頁面上有文檔,其中“ Calendar API頁面”未提及“將您的服務帳戶授予域名權限”部分。 該部分有7個步驟,需要完成。
BTW與個人帳戶管理網站admin.google.com甚至不可用。 因此,使用@ gmail.com帳戶執行這7個步驟是不可能的。
然后,當客戶在Google Apps管理控制台>安全>高級設置>管理OAuth客戶端訪問權限中獲得授權時 ,代碼就會開始運行。
有一個適合我的代碼:
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<EventReminder>(
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();
}
}
}
產生的輸出看起來如此:
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
=====================
第一項活動是每周一次的全日活動系列。 第二個是第一個更新的單個事件(具有相同的UID)。 第三是一小時的單一事件。 最后一個是由上面的代碼創建的。
希望這能幫助他人節省時間。
我不確定您的代碼有什么問題我認為它是如何加載密鑰文件的。 也可能是因為服務帳戶是您登錄的用戶,因此您無需向UserAccountCredential發送用戶 。 我不確定你為什么要發送某人的Gmail電子郵件。
using Google.Apis.Auth.OAuth2;
using System.Security.Cryptography.X509Certificates;
using Google.Apis.Calendar.v3;
namespace GoogleAnalytics.Service.Account
{
class Program
{
static void Main(string[] args)
{
//Install-Package Google.Apis.Calendar.v3
string serviceAccountEmail = "1046123799103-6v9cj8jbub068jgmss54m9gkuk4q2qu8@developer.gserviceaccount.com";
var certificate = new X509Certificate2(@"C:\Users\HP_User\Documents\GitHub\Google-Analytics-dotnet-ServiceAccount\GoogleAnalytics.Service.Account\Diamto Test Everything Project-bc63fd995bd7.p12", "notasecret", X509KeyStorageFlags.Exportable);
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = new[] { CalendarService.Scope.Calendar }
}.FromCertificate(certificate));
// Create the service.
var service = new CalendarService(new CalendarService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "CalendarService API Sample",
});
// define the new Calendar
Google.Apis.Calendar.v3.Data.Calendar calendar = new Google.Apis.Calendar.v3.Data.Calendar();
calendar.Description = "New Calendar";
calendar.Summary = "New Calendar Summary";
// Insert the Calendar
service.Calendars.Insert(calendar).Execute();
// List The Calendar
var calList = service.CalendarList.List().Execute().Items;
}
}
}
此代碼經過測試,它向您展示了如何為服務帳戶創建初始日歷。 如果不創建日歷,它將返回0個日歷,您需要記住先創建一個日歷。
我有同樣的問題,它在遠程服務器上工作正常,但在本地服務器上我得到了那個錯誤,長時間的故事短暫幾小時的頭痛我發現問題來自我的系統時鍾,只是通過這些步驟
1.單擊系統中的時鍾
2.單擊更改日期和時間設置...
3.單擊“Internet時間”選項卡
4.單擊“更改設置”
然后終於使用其中一個時間服務器更新你的時鍾
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.