Leave a comment

Your email address will not be published. Required fields are marked *

93 thoughts on “Google Calendar API Authentication with C#

  • Ronny

    Hi Linda,

    is there a way to configure the auth-uri before calling the GoogleWebAuthorizationBroker.AuthorizeAsync method?
    I want to append the “login_hint=user@example.com” with a given user email to open the browser-login-process with this user prefilled! I want to prevent that the user authorize the app with the wrong user account.
    Is this possible?

    Cheers,
    Ronny

      • Ronny

        Hi,

        i have looked at the source and I found no option to do that… maybe change the source of the library and use that instead directly from google…

        The important class is the GoogleAuthorizationCodeFlow.Initializer class, because it holds the auth-url. it is defined in GoogleAuthConsts as a const string…

        I tried to subclass GoogleAuthorizationCodeFlow.Initializer and override the getter/setter for AuthorizationServerUrl but the problem is the conversion back to GoogleAuthorizationCodeFlow.Initializer…

        Any ideas?

  • Ronny

    Hi Linda,

    here is my solution:

    using Google.Apis.Auth.OAuth2;
    using Google.Apis.Auth.OAuth2.Flows;
    using Google.Apis.Auth.OAuth2.Requests;
    using Google.Apis.Util.Store;
    using System;
    using System.Collections.Generic;
    using System.Threading;
    using System.Threading.Tasks;

    namespace MyOAuth2
    {
    //own implementation to append login_hint parameter to uri

    public class MyOAuth2WebAuthorizationBroker : GoogleWebAuthorizationBroker
    {
    public new static async Task AuthorizeAsync(ClientSecrets clientSecrets,
    IEnumerable scopes, string user, CancellationToken taskCancellationToken,
    IDataStore dataStore = null)
    {
    var initializer = new GoogleAuthorizationCodeFlow.Initializer
    {
    ClientSecrets = clientSecrets,
    };
    return await AuthorizeAsyncCore(initializer, scopes, user, taskCancellationToken, dataStore)
    .ConfigureAwait(false);
    }

    private static async Task AuthorizeAsyncCore(
    GoogleAuthorizationCodeFlow.Initializer initializer, IEnumerable scopes, string user,
    CancellationToken taskCancellationToken, IDataStore dataStore = null)
    {
    initializer.Scopes = scopes;
    initializer.DataStore = dataStore ?? new FileDataStore(Folder);
    var flow = new MyAuthorizationCodeFlow(initializer, user);

    // Create an authorization code installed app instance and authorize the user.
    return await new AuthorizationCodeInstalledApp(flow, new LocalServerCodeReceiver()).AuthorizeAsync
    (user, taskCancellationToken).ConfigureAwait(false);
    }
    }

    public class MyAuthorizationCodeFlow : GoogleAuthorizationCodeFlow
    {
    private readonly string userId;

    /// Constructs a new Google authorization code flow.
    public MyAuthorizationCodeFlow(Initializer initializer, string userId)
    : base(initializer)
    {
    this.userId = userId;
    }

    public override AuthorizationCodeRequestUrl CreateAuthorizationCodeRequest(string redirectUri)
    {
    return new GoogleAuthorizationCodeRequestUrl(new Uri(AuthorizationServerUrl))
    {
    ClientId = ClientSecrets.ClientId,
    Scope = string.Join(” “, Scopes),
    //append user to url
    LoginHint = userId,
    RedirectUri = redirectUri
    };
    }
    }
    }

    • Francesco Guerricchio

      It appears the problem is the async and await keywords, deleting those all work correctly

      following the working code:

      using Google.Apis.Auth.OAuth2;
      using Google.Apis.Auth.OAuth2.Flows;
      using Google.Apis.Auth.OAuth2.Requests;
      using Google.Apis.Util.Store;
      using System;
      using System.Collections.Generic;
      using System.Threading;
      using System.Threading.Tasks;
      using Google.Apis.Json;
      using System.Net.Http;
      using Google.Apis.Auth.OAuth2.Responses;
      using Google.Apis.Requests;
      using Google.Apis.Requests.Parameters;

      namespace MobiSync.Providers.GMAIL.Helpers
      {
      //own implementation to append login_hint parameter to uri

      public class CustomOAuth2WebAuthorizationBroker : GoogleWebAuthorizationBroker
      {
      public new static Task AuthorizeAsync( ClientSecrets clientSecrets,
      IEnumerable scopes, string user, CancellationToken taskCancellationToken,
      IDataStore dataStore = null )
      {
      var initializer = new MyAuthorizationCodeFlow.Initializer
      {
      ClientSecrets = clientSecrets,
      };
      return AuthorizeAsyncCore( initializer, scopes, user, taskCancellationToken, dataStore );
      }

      private new static Task AuthorizeAsyncCore(
      MyAuthorizationCodeFlow.Initializer initializer, IEnumerable scopes, string user,
      CancellationToken taskCancellationToken, IDataStore dataStore = null )
      {
      initializer.Scopes = scopes;
      initializer.DataStore = dataStore ?? new FileDataStore( Folder );
      var flow = new MyAuthorizationCodeFlow( initializer, user );

      // Create an authorization code installed app instance and authorize the user.
      return new AuthorizationCodeInstalledApp( flow, new LocalServerCodeReceiver( ) ).AuthorizeAsync
      ( user, taskCancellationToken );
      }
      }

      public class MyAuthorizationCodeFlow : GoogleAuthorizationCodeFlow
      {
      private readonly string userId;

      /// Constructs a new Google authorization code flow.
      public MyAuthorizationCodeFlow( Initializer initializer, string userId )
      : base( initializer )
      {
      this.userId = userId;
      }

      public override AuthorizationCodeRequestUrl CreateAuthorizationCodeRequest( string redirectUri )
      {
      System.Diagnostics.Debug.WriteLine( “I’m here”);
      return new GoogleAuthorizationCodeRequestUrl( new Uri( AuthorizationServerUrl ) )
      {
      ClientId = ClientSecrets.ClientId,
      Scope = string.Join( ” “, Scopes ),
      //append user to url
      LoginHint = userId,
      RedirectUri = redirectUri
      };
      }
      }
      }

    • Administrator
      Linda Lawton

      Unfortunately i don’t think that i can. This requires that you have a domain registered. The only domain i own is this one and it runs PHP. I would need access to a domain on a windows server to test this.

    • Administrator
      Linda Lawton

      Unfortunately i don’t think that i can. This requires that you have a domain registered. The only domain i own is this one and it runs PHP. I would need access to a domain on a windows server to test this.

  • Mayuresh

    Hi Linda

    I read your tutorials for Oauth 2 and all found to be very helpful. Thanks for sharing the tutorials. However I am facing one problem. I am accessing calendars using my C# application. Application is authenticate using user credentials. When user consent launches in web browser user close it without allow or cancel. In this scenario Google don’t return any value and application gets hang. How can we come to know that user cancel the user consent?

    Thank you.

    • Administrator
      Linda Lawton

      Add a try catch around the GoogleWebAuthorizationBroker section before you create the service. If the user hits cancel it will return

      InnerException = {“Error:\”access_denied\”, Description:\”\”, Uri:\”\””}

  • Mayuresh

    I am already adding try catch around GoogleWebAuthorizationBroker but not throwing any exception. When user consent tab in web browser is closed (Alt + F4) without clicking on Allow or Cancel application gets stuck.
    Could you please suggest any solution on this?

    try
    {
    GogleWebAuthorizationBroker gWebAuthorizationBroker = new GoogleWebAuthorizationBroker();
    CientSecrets _ClientSecret = new ClientSecrets();
    _ClientSecret.ClientId = ClientId.;
    _ClientSecret.ClientSecret = ClientSecret;
    FileDataStore objFileDataStore = new FileDataStore(applicationPath, true);

    System.Threading.Tasks.Task userCred = GoogleWebAuthorizationBroker.AuthorizeAsync(_ClientSecret,
    new[]{ CalendarService.Scope.Calendar},
    Username,
    System.Threading.CancellationToken.None,
    objFileDataStore);

    UserCredential _userCredentials = await userCred;
    }
    catch (Exception)
    { }

  • Saar

    Hi Linda, is there any way to authenticate the user using user name and password without opening the web browser?
    I would like to build the application where the user inserts his name and password.

    Thanks,
    Saar

  • Mikkel Nilesen

    What is the best way to debug?
    I keep getting an internal error, when trying to create UserCredential – but the error message is not very informative.

    When testing a webservice on localhost, what should the redirect uri be?

    BR, Mikkel

    • Administrator
      Linda Lawton

      When testing a web-service localhost, http://localhost/Oauth2.aspx or create a Client ID for native application but what ever you do don’t release it with the Client ID for native application credentials. I just find it easier to use that then you don’t have to deal with the hole redirect uri nightmare with visual studio adding ports.

      Do a try catch what exactly is the error its coming with?

      • Mikkel Nilesen

        I got it working on my local machine – using http://localhost/authorize/ as redirect uri

        But won’t work on hosted server. According to Fiddler I get these exceptions.

        {“Message”:” at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)\r\n at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)\r\n at System.Threading.Tasks.Task`1.get_Result()\r\n at DSInettetUserControls.CalendarServicesV3.GetFeed(String start, String end, Int32 numberToRetrieve, String calendarID)”,”StackTrace”:” at DSInettetUserControls.CalendarServicesV3.GetFeed(String start, String end, Int32 numberToRetrieve, String calendarID)”,”ExceptionType”:”System.ArgumentException”}

        It really drives me crazy!

        Im using your idatastore btw…works great. Thx 🙂

  • Greg Frazier

    Hi Linda,

    “var certificate = new X509Certificate2(keyFilePath, “notasecret”, X509KeyStorageFlags.Exportable);”

    What is the KeyFilePath? Is this the path of the location of the certificate file on the developer’s computer? Or is it a path to the Google Developers Console? I’m developing apps on a newer laptop than the one I created the service account info from. Do I need to generate a new P12 key? If I do, will it replace the current P12 key or will I have two keys? I plan to use the Service Account authentication.

  • Mikkel Nilesen

    Hi Linda,

    I need someone (you I hope) to point me in the right direction.

    On our company intranet we have a calendar, we use for internal stuff….like booking a meeting room. Behind the calendar there is a google calendar, to which I make some standart api calls like insert, delete, getEntries etc.

    Since the Calendar V3 update it doesn’t work anymore of course, so I need to change my api calls – but Im not sure how.

    What I want to acomplish is:
    I have a google calendar to which I will allow people to insert, delete and change entries via a custom interface that use google api v3 (.Net).
    They (the people) might NOT have a google account on their own.
    They (the people) DON’T know the password or username to the calendar account.
    The calendar stuff is not a secret – I accept low sescurity if necessary.

    As I understand, I can only use “Public API access” to show entries, but not add or delete. Is that correct?

    What kind of auth. would you recommend for a solution like this?

    Best Regards, Mikkel

    • Administrator
      Linda Lawton

      I would go with a service account if i was you. You wont need a login. Drawback no one will be able to see it on the Web version of Google Calendar but that doesn’t sound like it will be an issue for you.

      • Vinay

        Hi,

        I’ve a similar case, where I’m building solution for meeting rooms.
        In my case, I need to show calendar events of multiple google accounts. I want only readonly access to the calendar.

        please suggest, how can I do that.

        Vinay

        • Linda Lawton
          Linda Lawton Post author

          I can think of a few ways of doing that.

          1. Create a service account give the owners of the accounts the service account email address ask them to grant it access to the calendar in question.
          2. Use Oauth2 and request read only access to the users calendars.

  • Lukas Raab

    Hi Linda,
    is it possible to access to any Google Calendar (user enters a public link or username and password)? (readonly)
    I am using the .net library.

    Thanks Lukas!

    • Administrator
      Linda Lawton

      No you cant use Client login (Login and password) to access any of the Google APIs useing the .net client library. As of April 20th 2015 you wont be able to access any of the Google APIs like this.

      You need to use Open Authentication.

  • raj

    I have 100 google calendar user and I need to create event in their calendar. Event is different from one to another. I have all 100 users gmail id. Please suggest me how to achieve this?
    All event related information is available in Database.
    1. Should I need to use OAuth2 ?
    2. How to achieve this 100 users? Do I need to create 100 OAuth2 Authentication?
    Please advice. Thanks.

    • Administrator
      Linda Lawton

      You will need to have each of your users authenticate your application, then you can save the refresh-token somewhere say the database. Once you have there permissions you will be able to add events to there calendar when ever you like. Yes you will need to use Oauth2.

  • richwood

    Hello Linda, I hope you’re there.
    I’m attempting to stand on your shoulders and I keep falling off !
    I have a main goog calendar, while logged in, i created 2 calendars, made them public and shared them to other gmail accounts. The account for ‘main’ has a project, api’s enabled and various credentials,. the important one being the native app creds. CLIENT_ID + CLIENT_SECRET. In your Clndr-Api-dotnet console app, I put in the databasedatastore code from your api auth project. I set the client_id, client secret, calendarid and the constructed dbdatastore, all good. On 1st run, I get the auth challenge, grant it, the token is captured and subsequent runs utilize the refresh token and all is well. Each calendar id was handled in the same way, 1st run auth, capture the token; insert to db as separate row etc. I am using the same client_id and client_secret for all these “child” calendars since “main” is the creator / owner of them
    I’m off in the stix with the following behavior though. For the first child calendarid, the google.apis.calendar.v3.data.events object AccessRole property returns with “owner” ..all good. For the 2nd (and subsequent) calendarid’s the role returns as “reader” ..yikes.. Honest to Pete, these calendars are set up exactly the same way. I’ve been spinning my wheels for more than a few hours, trial and error with no joy. I’m leaning toward the reason being something “dumb” & not fathoming what dumb might be. I’m requesting your opinion. Can you suggest any approach to diagnosis and or fix. Rich in Austin.

  • richwood

    Ok, it’s a “dumb” for sure. In my implementation, the service account is totally adequate for doing crud on various child calendars: the scenario being a “master” calendar where n number of “child” calendars are created and shared to appropriate gmail accounts, Even though each child calendar is shared allowing R/W by the associated gmail user, that is not enough to allow the service account to do anything but read. The appropriate role has to be added. One way to add is to use the “developers.google.com.google-apps/calendar.reference/acl/insert/#example” first. From the top, the steps are 1. create a gmail account. then a calendar (this is your container calendar), 2 Since you are logged in on that gmail account, go on the console.developers.google site, create a project on that account, enable the calendar api, derive the oauth service account creds.. 3. go back over to the calendar, add a child calendar, 4.share that child calendar to a gmail email of your choice, (make sure to accept the invite sent to that email while logged in on that email account) . 4. Go back over and make sure you’re logged into the account that owns the calendar and project, go to the “master” calendar , find the child calendar, got into it’s settings, and copy the calendar id. 5. Go back over to the developers.google.com.google-apps/calendar.reference/acl/insert/#example, turn on oAuth 2.0 (you’ll see the auth window come and go) scroll down to the “try it! ” area and put the calendarid in the calendarid box, put in “writer” in the role box, under “scope” put “user” for the Type and add a value param. In the value param paste in your SERVICE_ACCOUNT_EMAIL. 6. Click Execute. Note the http 200 -or- fix an error. Once this role has been added, the service account will be able to r/w events to the child calendars.
    This worked for me and is easier to deploy than using the native app route. Rich

      • raza

        Thanks for your replay,
        Actually my first application on google.apis
        please help me
        i tried you code from github,
        i tried to develop a simple application to create an event in google calender
        from win forms applications
        by using the service account auth
        am receiving the error
        “Unexpected character encountered while parsing value: <. Path '', line 0, position 0."

        My Code:

        CalendarService service;

        String SERVICE_ACCOUNT_EMAIL = "XXXXXXXXXXXXXXXXX@developer.gserviceaccount.com";
        string SERVICE_ACCOUNT_KEYFILE = @"d:\EVENTREQUEST-a873840e956d.p12";
        service = Authentication.AuthenticateServiceAccount(SERVICE_ACCOUNT_EMAIL, SERVICE_ACCOUNT_KEYFILE);

        // Authenticate Oauth2
        eventdata.Summary = "title";
        eventdata.Location = "location";
        eventdata.Description = "description";
        EventDateTime start = new EventDateTime();
        start.DateTime = DateTime.Now;
        eventdata.Start = start;
        EventDateTime end = new EventDateTime();
        end.DateTime = DateTime.Now.AddHours(1);
        eventdata.End = end;
        eventdata = DaimtoEventHelper.insert(service, "1", eventdata);

  • Darrell Sveistrup

    Hi Linda,

    You example show using the P12 file generated to create the ServiceAccountCredential’s
    Do you know how to do the same with the json file option?

    I’m guessing that you would not call the “.FromCertificate(certificate)”
    And would be setting the key, but not sure what mapping would be or how to convert.

  • keith

    hi I’ve been having some difficulty with creating events onto google calendar with .net, I couldn’t fully make use of your sample codes as I’m really just bad at .net

  • Neeraj Singh

    I need to use Google Calendar Api from ASP.NET Web Api application. Is there a substitute available for RedirectResult as ApiControllers doesn’t have this and Google’s Mvc4 library uses ResultRedirect to get the authorization.

  • Octavio Manzano

    Hi, I have an app that uses Authentication.AuthenticateOauth and works perfectly on localhost: i can get the events of the calendar’s users and insert new events too but when deply my App to production server with IIS 7.5 my app doesn’t work. I have all dll on the bin, can you help me please?

  • Andy

    Just wanted to say thanks for all your examples.
    They helped me immensely in starting to secure some of our applications using Google instead of LDAP.

  • Javier

    Hi Linda! Thanks for the tut, it is great!
    I’m getting this error: “Key MUST have a value” in the credential line, do you know what that is?
    Thx
    Javier

  • Tom Weissert

    Hi Linda,

    Thank you for your excellent work. I have two problems, here is the first.
    I’m trying to use oauth2 to let a user authenticate and then add events, blah blah,
    my authentication code is below.
    The problem is that this page hangs and never returns, the consent screen never appears.

    using System;
    using System.Linq;
    using Google.Apis.Auth.OAuth2;
    using Google.Apis.Calendar.v3;
    using Google.Apis.Calendar.v3.Data;
    using Google.Apis.Services;
    using System.Configuration;
    using System.Threading;

    namespace Events
    {
    public partial class Events_newauth2 : System.Web.UI.Page
    {
    CalendarService service;

    protected void Page_Load(object sender, EventArgs e)
    {
    if (!IsPostBack)
    {
    if (service == null) { service = CreateService(); }
    CalendarList result = service.CalendarList.List().Execute();

    foreach (CalendarListEntry calendar in result.Items)
    {
    lblNote.Text += “” + calendar.Id + ” : ” + calendar.Summary;
    }
    }
    }
    protected CalendarService CreateService()
    {
    UserCredential credential;
    try
    {
    credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
    new ClientSecrets
    {
    ClientId = ConfigurationManager.AppSettings[“ClientID”],
    ClientSecret = ConfigurationManager.AppSettings[“ClientSecret”]
    },
    new[] { CalendarService.Scope.Calendar },
    “tweissert@agnesirwin.org”,
    CancellationToken.None,
    new DatabaseDataStore(“Websrv”, “aspnet”, “123”, “CalendarEvents”, “GoogleUser”)).Result;
    }
    catch
    (Exception ex)
    {
    lblNote.Text = ex.Message;
    return null;
    }
    CalendarService theservice = new CalendarService(new BaseClientService.Initializer()
    {
    HttpClientInitializer = credential,
    ApplicationName = “AIS Calendar Tool”,
    });
    return theservice;
    }
    }
    }

  • dantha

    Hi Linda,

    I am using Google Calendar API Service Account Authentication for reservation application.

    I am having below error: “An error occurred while sending the request. —> System.Net.WebException: The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel. ”

    it works fine on local pc. but when I upload it into the server it gives an error. (below). please help me to resolve this.

    2015-08-05 15:57:06,018 – Error when Insert to google cal ‘GoogleCalendarSync’ >>An error occurred while sending the request.
    2015-08-05 15:57:06,018 – ex.StackTrace’ >> at Google.Apis.Requests.ClientServiceRequest`1.Execute()
    at WebService.GoogleCalendarSync.GoogleCalendarSyncProcess(Int32 RsvId, String GroupId, String Summary, String Desc, String StartTime, String EndTime, String Location, String OrganizerEmail)
    2015-08-05 15:57:06,018 – ex.Source’ >>System.Net.Http.HttpRequestException: An error occurred while sending the request. —> System.Net.WebException: The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel. —> System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure.
    at System.Net.TlsStream.EndWrite(IAsyncResult asyncResult)
    at System.Net.PooledStream.EndWrite(IAsyncResult asyncResult)
    at System.Net.ConnectStream.WriteHeadersCallback(IAsyncResult ar)
    — End of inner exception stack trace —
    at System.Net.HttpWebRequest.EndGetRequestStream(IAsyncResult asyncResult, TransportContext& context)
    at System.Net.Http.HttpClientHandler.GetRequestStreamCallback(IAsyncResult ar)
    — End of inner exception stack trace —
    at Google.Apis.Requests.ClientServiceRequest`1.Execute()
    at WebService.GoogleCalendarSync.GoogleCalendarSyncProcess(Int32 RsvId, String GroupId, String Summary, String Desc, String StartTime, String EndTime, String Location, String OrganizerEmail)

    here are my code segments:

    var serviceAccountEmail = “*************nt.com”; // found https://console.developers.google.com
    var keyFilePath = @”D:\Production\apps.p12″; // Downloaded from https://console.developers.google.com
    service = Authentication.AuthenticateServiceAccount(serviceAccountEmail, keyFilePath);

    public static CalendarService AuthenticateServiceAccount(string serviceAccountEmail, string keyFilePath)
    {

    // check the file exists
    if (!File.Exists(keyFilePath))
    {
    log.Error(“AuthenticateServiceAccount >>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)
    {
    log.Error(“AuthenticateServiceAccount >>” + ex.Message);
    // Console.WriteLine(ex.InnerException);
    return null;

    }
    }

    please help me to solve this issue.

  • Finlay

    Hi Linda,

    Diamto.Google.Authentication/DatabaseDataStore.cs saves refresh token only, how about access token?
    CREATE TABLE dbo.GoogleUser(username nvarchar(4000), RefreshToken nvarchar(4000), Userid nvarchar(4000))

    Based on my experience with Calendar API v2, I suppose access token is useful for
    – health check whether the token is still valid
    – refresh itself
    – revoke a previously permitted access

    Any idea?

    • Linda Lawton
      Linda Lawton Post author

      No real reason to save the access token when it expires after an hour. You can just use the refresh token to get a new access token when ever you need. I am not aware of any limits to the number of times you can request a new access token or how often you can request it.

      – I don’t bother with health check normally i just request a new one.
      – you use the refresh token to revoke it i think not the access token. (But its been a while since i have done that i may be wrong.)

  • Caipigott

    Hello,

    thanks for your great tutorial.
    So far i could make it run, but i’m running into an error “GoogleWebAuthorizationBroker.AuthorizeAsync”

    “The character set provided in ContentType is invalid. Cannot read content as string using an invalid character set.”
    “UTF-8″‘ is not a supported encoding name. For information on defining a custom encoding, see the documentation for the Encoding.RegisterProvider method.\r\nParameter name: name”

    I already search an houre on the internet but without success.
    Do you have any idea what could be the problem?

    Thanks for your help in advance,
    greetings,
    Caipigott

    • Caipigott

      Hi,

      i’m sorry, i just found out that it’s up to the internet connection of my work. I guess it blocks the response, or something.
      No i used the connection of my celular and it worked.

      Greetings,
      Caipigott

  • Greg

    Hi Linda,

    Thanks for this tutorial. Have you done any tutorials yet on how to create an event on google calendar from a C# application in visual Studio?

    • Linda Lawton
      Linda Lawton Post author

      ///

      /// Adds an entry to the user's calendar list.
      /// Documentation:https://developers.google.com/google-apps/calendar/v3/reference/calendarList/insert
      ///

      /// Valid Autenticated Calendar service
      /// Calendar identifier.
      /// an event
      /// event resorce: https://developers.google.com/google-apps/calendar/v3/reference/events#resource
      public static Event insert(CalendarService service, string id, Event body)
      {
      try
      {
      return service.Events.Insert(body,id).Execute();
      }
      catch (Exception ex)
      {
      Console.WriteLine(ex.Message);
      return null;
      }
      }

      • Greg

        Ok, Thank You. I noticed that piece of the code was there after I posted the comment, Sorry. I’m going to give it a try now.

  • Mudasser

    I am wokring on Google calendar API using C#. I am devloping a web page that will access the my clients(specific user) calendar and display just the calendar’s information,events etc on web page. So, I don’t want the user to enter in their Google account information which is what oAuth wants to do.

    i used the following code

    string serviceAccountEmail = “serviceAccountEmail “;
    string filepath = Application.StartupPath + @”\file.p12”;
    var certificate = new X509Certificate2(filepath, “notasecret”,
    X509KeyStorageFlags.Exportable);

    ServiceAccountCredential credential = new ServiceAccountCredential(new
    ServiceAccountCredential.Initializer(serviceAccountEmail)
    {
    Scopes =
    new[] { CalendarService.Scope.Calendar }
    }.FromCertificate
    (certificate));

    BaseClientService.Initializer initializer = new
    BaseClientService.Initializer();
    initializer.HttpClientInitializer = credential;
    initializer.ApplicationName = “Google Calendar Sample”;
    CalendarService calservice = new CalendarService(initializer);

    //Follwoign line did’t get my calendar events
    EventsResource.ListRequest request = calservice.Events.List(“primary”);
    Events events = request.Execute();

    I want to access the calender of specific email and need to show all the events etc .

    Kindly help.

    Thanks

    Regards

    Mudasser

    • Linda Lawton
      Linda Lawton Post author

      Make sure you have taken the Service account email address and added it as a user on the Calendar in the Google Calendar website you can also find the Google Calendar id there, Primary isn’t going to work with a service account.

      • Mudasser

        I added the service account using my Google email,
        lets say my email is “abc@gmail.com” and service id generated is “gooleserviceygx@serviceaa-4789.ibm.gstrviceaccount.com”

        Then i created the public calendar(Calender Name:My events Calender) on using my Google account(abc@gmail.com),then created the Event in that public calender(My events Calender) lets say event is party.
        Then i edit my google calander setting(Shared: Edit settings) and add my service account in Share with specific people section.

        Following code i used
        string serviceAccountEmail = “gooleserviceygx@serviceaa-4789.ibm.gstrviceaccount.com “;
        string filepath = Application.StartupPath + @”\file.p12”;
        var certificate = new X509Certificate2(filepath, “notasecret”,
        X509KeyStorageFlags.Exportable);

        ServiceAccountCredential credential = new ServiceAccountCredential(new
        ServiceAccountCredential.Initializer(serviceAccountEmail)
        {
        Scopes =
        new[] { CalendarService.Scope.Calendar }
        }.FromCertificate
        (certificate));

        BaseClientService.Initializer initializer = new
        BaseClientService.Initializer();
        initializer.HttpClientInitializer = credential;
        initializer.ApplicationName = “Google Calendar Sample”;
        CalendarService calservice = new CalendarService(initializer);

        //Follwoing line did’t get my calendar events
        EventsResource.ListRequest request = calservice.Events.List(“primary”);
        Events events = request.Execute();

        Above line suppose to get event(party) which i added in my public calendar(My events Calender) but it is not getting.

        My requirement is whatever i added or add on my calender it should shows on my public website.

        • Linda Lawton
          Linda Lawton Post author

          A service account is not you, even though you created it with your personal gmail its still not you it has its own google calendar.

          calservice.Events.List(“primary”);

          Primary is the service accounts primary calendar which is not yours.

          You need to go back in the settings and find the calendar id for your personal calendar.

          • Linda Lawton
            Linda Lawton Post author

            If the calendar is public then you can use a public API key. If its someones personal calendar then you cant, you need to be authenticated to access private data.

        • Mudasser

          Can you kindly share some sample (C#) to get the public calender events using public key without being authenticated.

          Thanks in advance for help

        • Mudasser

          thanks for your help.Its so nice of you.
          Kindly just tell me, if i create a new calender by the following code, is it possible by code to make that calender as public.

          Calendar cal = new Calendar();
          cal.Summary = “calander created by code”;
          Calendar createdCalendar = service.Calendars.Insert(cal).Execute();

        • Mudasser

          And also kindly tell is there any way to get the public calendar only or any way to check either calender is public or not

          CalendarList clst = cservice.CalendarList.List().Execute();

          • Linda Lawton
            Linda Lawton Post author

            calendar list just shows you the list of calendars you have added to calendar list. i would do calendar.get that might show if the calendar is public or not.

  • Willem Luijk

    Hello Linda,

    I published the Daimto.GoogleSample.Analytics to azure and got this message:

    2016-04-11T21:06:06 PID[17220] Information System.Net.HttpListenerException (0x80004005): Access is denied
    2016-04-11T21:06:06 PID[17220] Information at Microsoft.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
    2016-04-11T21:06:06 PID[17220] Information at Microsoft.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccess(Task task)
    2016-04-11T21:06:06 PID[17220] Information at Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker.d__1.MoveNext()
    2016-04-11T21:06:06 PID[17220] Error
    2016-04-11T21:06:06 PID[17220] Error Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object.
    2016-04-11T21:06:06 PID[17220] Error at Daimto.Google.Sample.Analytics.DaimtoAnaltyicsManagmentHelper.AccountSummaryList(AnalyticsService service)
    2016-04-11T21:06:06 PID[17220] Error at Daimto.Google.Sample.Analytics.

    Do you have any clue?

    • Mudasser

      Hello,
      I created the sample Asp.net application to get all the calender and add event in a calendar.My Application is working fine when i run it using Visual Studio it successfully load the page,show all calendar info, add event in calendar.But when i deploy the app on IIS, page never load and it gives the “Request timed out” exception.Kindly help

      Following is the code

      private CalendarService InitGoogleService()
      {
      UserCredential credential;
      string path = Server.MapPath(“~”) + @”\GCSc.json”;
      string credPath = Server.MapPath(“~”) + @”\Calendar_Data”;
      credential = GoogleWebAuthorizationBroker.AuthorizeAsync(new ClientSecrets
      {
      ClientId = “My Client Id”,
      ClientSecret = “My Client Secret”
      }, Scopes, “user”, CancellationToken.None, new Google.Apis.Util.Store.FileDataStore(credPath)).Result;

      CalendarService service = new CalendarService(new BaseClientService.Initializer()
      {
      HttpClientInitializer = credential,
      ApplicationName = ApplicationName,
      });
      return service;
      }

  • Henry Tehrani

    hello:
    I am trying to import calendar settings into google calendar and followed your instructions, but I get an access error when I publish my code to staging server. codes works great in my local machine, how do I get around this ? any suggestions?
    here is my code:
    String gpath = dataPath + “/credentials/siteAPI.json”;
    UserCredential credential;
    ClientSecrets secrets = new ClientSecrets()
    {
    ClientId = “aaaaa”,
    ClientSecret = “yyyyy”,
    };
    using (var stream = new FileStream(gpath, FileMode.Open, FileAccess.Read))
    {
    //string folder = System.Environment.GetFolderPath( System.Environment.SpecialFolder.ApplicationData);
    //folder = Path.Combine(Environment.GetFolderPath(System.Web.HttpContext.Current.Server.MapPath(“YourFolderName”), folder));
    String g = dataPath + “\\credentials”;

    credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
    //GoogleClientSecrets.Load(stream).Secrets,
    secrets,
    new[] { CalendarService.Scope.Calendar },
    “user”,
    CancellationToken.None ,
    new FileDataStore(g)
    ).Result;
    }
    at this stage I get :
    System.ComponentModel.Win32Exception: Access is denied at Microsoft.Runtime.CompilerServices.TaskAwaiter.T …..

    error
    many thanks
    Henry

    • Linda Lawton
      Linda Lawton Post author

      I would post your question to stackoverflow make sure to tag it google-calendar and google-apis-dotnet-client it will be easier to fix your problem with more eyes on it.

    • Linda Lawton
      Linda Lawton Post author

      You need the client id and client secrete to use the refresh token. You need a client id and client secrete to get an access token. Client id and client secret identify your application to google you will always need that.