Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DotNetOpenAuth with Google Calendar Feed

I have been racking my brain for a few days trying to get a list of calendars from Google using DotNetOpenAuth.

I can successfully get a list of contacts using the DotNetOpenAuth Samples. I have integrated it with my domain using the OpenId+OAuth. Everything works great to get a list of contacts.

So from there I modified the code to try to retrieve a list of Calendars and I keep getting a 401 Unauthorized error.

I know it is authorizing because I can get the contact list. Does anyone have a code example how they are retrieving calendars or calendar events using the DotNetOpenAuth with Google???

Thanks

Update:

Thanks for the response. I have read everything I can get my hands on. Here is what I have done so far

Step 1: I created a new GetCalendarEndPoint in the GoogleConsumer.cs

private static readonly MessageReceivingEndpoint GetCalendarEndpoint = new MessageReceivingEndpoint("https://www.google.com/calendar/feeds/default", HttpDeliveryMethods.GetRequest);

Step 2: Next I created a new method GetCalendars patterned after the GetContacts Method in GoogleConsumer.cs - (Rebuilt the dll etc.)

    public static XDocument GetCalendars(ConsumerBase consumer, string accessToken, int maxResults/* = 25*/, int startIndex/* = 1*/) {
            if (consumer == null)
            {
                throw new ArgumentNullException("consumer");
            }

            var request = consumer.PrepareAuthorizedRequest(GetCalendarEndpoint, accessToken);
            var response = consumer.Channel.WebRequestHandler.GetResponse(request);
            string body = response.GetResponseReader().ReadToEnd();
            XDocument result = XDocument.Parse(body);
            return result;

Step 3: In my Application I modified the ScopeURI to the the Calendar URI from GoogleConsumer as follows

private IAuthenticationRequest GetGoogleRequest()
{
    Realm realm = Request.Url.Scheme + Uri.SchemeDelimiter + Global.GoogleTokenManager.ConsumerKey + "/";
    IAuthenticationRequest authReq = relyingParty.CreateRequest(GoogleOPIdentifier, realm);

    // Prepare the OAuth extension
    string scope = GoogleConsumer.GetScopeUri(GoogleConsumer.Applications.Calendar);
    Global.GoogleWebConsumer.AttachAuthorizationRequest(authReq, scope);

    // We also want the user's email address
    var fetch = new FetchRequest();
    fetch.Attributes.AddRequired(WellKnownAttributes.Contact.Email);
    authReq.AddExtension(fetch);

    return authReq;
}

However, when I run the app I get 401 Unauthorized when I make the following call

 var calendars = GoogleConsumer.GetCalendars(Global.GoogleWebConsumer, State.GoogleAccessToken, 25, 1);

I have also checked that the State.GoogleAccess token exists by simply displaying it on my screen before I trigger the method that makes this call.

Again, if I exectute

var calendars = GoogleConsumer.GetContacs(Global.GoogleWebConsumer, State.GoogleAccessToken, 25, 1);

then it works??????? Thanks for you help.

like image 761
Brett Allred Avatar asked Oct 02 '10 08:10

Brett Allred


2 Answers

I've been suffering through exactly the same thing for most of the weekend.

I think that after much fiddling with Fiddler I've found the cause and have a solution which, although not pretty, seems to work. I found that I was able to access the calendar feed by copying and pasting the DNOA-generated Uri into a browser, but always got a 401 when attempting programmatic access. This is apparently because the default auto-redirect behavior of HttpWebRequest discards any cookies that the redirect is attempting to set. The Contacts feed doesn't set any cookies during the redirect, so it is immune.

The first time you request a calendar feed (even with a properly constructed and signed OAuth request), Google replies with a redirect containing a cookie. If you don't present that "calendar cookie" at the same time as your feed request you will get a 401 Unauthorized when you attempt to follow the redirect to the feed.

here's the cookie-setting header from Google:

HTTP/1.1 302 Moved Temporarily
Set-Cookie: S=calendar=y7AlfgbmcqYl0ugrF-Zt9A;Expires=Tue, 10-Jan-2012 03:54:20 GMT;Secure

Here's what I'm doing to make it work:

// wc: WebConsumer
var calRequest = wc.PrepareAuthorizedRequest(erp2, authTokenRsp.AccessToken);
// need to stop redirect to capture calendar cookie token:
calRequest.AllowAutoRedirect = false;
var calResponse = calRequest.GetResponse();
var redirectCookie = calResponse.Headers[System.Net.HttpResponseHeader.SetCookie];

var cookiedCalRequest = wc.PrepareAuthorizedRequest(erp2, authTokenRsp.AccessToken);
cookiedCalRequest.Headers[System.Net.HttpRequestHeader.Cookie] = redirectCookie;
var calFeedResponse = cookiedCalRequest.GetResponse();
like image 76
Dave Avatar answered Oct 23 '22 00:10

Dave


Have you read the Google Calendar data API documentation to make sure you have the right endpoints programmed in? Have you also modified the code that acquires the access token to request access to Google Calendar in addition to Google Contacts? The access token in the sample only gets Contacts permissions unless you change it.

like image 1
Andrew Arnott Avatar answered Oct 22 '22 23:10

Andrew Arnott