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 regarding authorization. Most of Google samples can't be even compiled because of outdated libraries and classes used.
So I found some example over interned and receive error. Could someone please look on my sample and tell what am I doing wrong?
Preparatory steps:
- I created a project in my private Google account.
- In project developer console, under APIS & AUTH -> Credentials, I generated Service Account. Then clicked on "Generate P12 key" and downloaded the .p12 file.
- Under APIS & AUTH -> APIs, switched on "Calendar API"
Then created console app and managed to install OAuth and Calendar nuget packages. There are:
- Google APIs Auth Client Library, Google.Apis.Auth 1.8.1
- Google APIs Client Library, Google.Apis 1.8.1
- Google APIs Core Client Library, Id: Google.Apis.Core 1.8.1
- Google.APIs.Calendar.v3 Client Library, Google.Apis.Calendar.V3 1.8.1.860
There is a code found and adapted to my needs:
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();
}
}
}
The communication with Google API which I see in the app and Fiddler is:
Request :
Host: HTTPS accounts.google.com, URL: /o/oauth2/token
Assertion: long binary string
grant_type: urn:ietf:params:oauth:grant-type:jwt-bearer
Response:
HTTP/1.1 400 Bad Request Content-Type: application/json Cache-Control: no-cache, no-store, max-age=0, must-revalidate Pragma: no-cache Expires: Fri, 01 Jan 1990 00:00:00 GMT Date: Thu, 24 Jul 2014 06:12:18 GMT X-Content-Type-Options: nosniff X-Frame-Options: SAMEORIGIN X-XSS-Protection: 1; mode=block Server: GSE Alternate-Protocol: 443:quic Transfer-Encoding: chunked
1f { "error" : "invalid_grant" } 0
Please help and thanks in advance!