Friday, August 6, 2010

C#: Doing stuff with Google using OAuth - an idiot's guide

I have been playing around with OAuth and connecting to Google apps. After wading through the OAuth standards and Google API docs I decided a library was the way forward, so downloaded DotNetOpenAuth.

As often seems to be the case with freely provided software, it is awesome and well documented at the reference level, but not very good at handholding you through a basic scenario; although that may be due to my preferred way of starting up a blank project and attempting to get a simple application working rather than starting up a sample project and modifying it :o)

I eventually found a good example of what I wanted to do in Samples\OAuthConsumerWpf, but having done hardly any WPF and being too old and grumpy to use lambda functions, it still took a while to get my head round it and get a simple Windows Forms app going.

This is what I did:

  1. Created a new Windows Forms application in VS2008
  2. Added a reference to the DotNetOpenAuth assembly.
  3. Copied the files GoogleConsumer.cs and Util.cs from \Samples\DotNetOpenAuth.ApplicationBlock to my application.
  4. You also need an object implementing IConsumerTokenManager. The samples use the InMemoryTokenManager, which is fine for testing - obviously you will need to re-authorise the application on each run, and a useful application would have some kind of backing store.

    The InMemoryTokenManager is located in \Samples\DotNetOpenAuth.ApplicationBlock\InMemoryTokenManager.cs but is disabled outside the samples using compiler directives; I copied it into my new project and removed the compiler directives because I'm too lazy to change the DEFINEs - and again, I prefer to start with nothing and work up to a working sample app in order to get my head round things.

Once you have all these files, you can talk to Google from a Windows Forms app with a tiny amount of code, most of which is palmed off to the GoogleConsumer object in GoogleConsumer.cs.

If you, like me, are new to OAuth programming, the sequence is as follows:

  1. Create a DesktopConsumer that will talk to Google, using the GoogleConsumer.ServiceDescription and a new IConsumerTokenManager for the consumer key anonymous and secret anonymous.

    The consumer key and secret identify your application - it will not be registered with Google, so you use anonymous - see http://code.google.com/apis/accounts/docs/OAuth_ref.html#SigningOAuth.

  2. Call GoogleConsumer.RequestAuthorization with this consumer and flags specifying the Google apps you want access to. This returns the URL of a page that will ask the user to authorise your application, and a request token which is used later in the process.
  3. So far, you have just told Google you want to access application data; at this point, no specific user has been mentioned. You now need to start up a web browser to the URL returned by GoogleConsumer.RequestAuthorization. This will allow a user to grant access to an application, and give them a verification key. The easiest way to achieve this is to start off the browser with System.Diagnostics.Process.Start(url) and show a modal window asking for the verification key to be pasted when it is retrieved.
  4. You now use the ProcessUserAuthorization of the DeskTopConsumer instance to get an access token, passing in the request token returned in step 2 and the verification code pasted in by the user.
  5. Once you have the access token, you can use that and the consumer to start interacting with Google apps!

Assuming all of the required DotNetOpenAuth files have been referenced or copied in as above, here is the (very simple) code to post a blog entry on Google:

// You will need the following using directives:
using DotNetOpenAuth.OpenId.Extensions.OAuth;
using DotNetOpenAuth.OAuth;
using DotNetOpenAuth.OAuth.ChannelElements;
using DotNetOpenAuth.OAuth.Messages;

// Needed for GoogleConsumer
using DotNetOpenAuth.ApplicationBlock;
// Set up consumer
DesktopConsumer consumer = new DesktopConsumer(GoogleConsumer.ServiceDescription, new InMemoryTokenManager("anonymous", "anonymous"));

// Get the request token and user access authorisation URL
String requesttoken;
Uri authuri = GoogleConsumer.RequestAuthorization(consumer, GoogleConsumer.Applications.Blogger, out requesttoken);

// Start up a browser for the user to grant access and be given the verification key
System.Diagnostics.Process.Start(authuri.AbsoluteUri);

// I have not documented my FormGetKey, but it is a simple form with one textbox and an Ok button on 
// it that just sits there being modal until the user pastes the verification key in and clicks Ok.
FormGetKey form = new FormGetKey();
form.ShowDialog();

// Oh yes, and the form has a public property which is simply { get { return textboxVerificationKey.Text; } } :o)
String vercode = form.VerificationCode;
//

// Get the access token given the request token and the verification code
AuthorizedTokenResponse grantedAccess = consumer.ProcessUserAuthorization(requesttoken, vercode);
String accesstoken = grantedAccess.AccessToken;
//

// Now we are authorized, we have an access token, and we can do stuff
GoogleConsumer.PostBlogEntry(consumer, accesstoken, "http://mylovelyblog.blogspot.com", "OAuth test", XElement.Parse("<p>OAuth test content.</p>"));
//

The next step in the process is providing a more useful implementation of IConsumerTokenManager with a backing store and using the tokens from that. I will post a similarly lift-up-flaps level post on that when I have tried it out, and again with a web app based system.

Looking at the code now, it must be just the fact that it's Friday that I found this complicated...

5 comments:

  1. Great post. You might check out LinqToTwitter's IConsumerTokenManager for desktop apps for inspiration -- for better or worse. :)

    ReplyDelete
  2. Excellent post!! This is far better than anything else that is out on the web. One question though. I understand that there are many functions like Getcontacts() and PostBlogEntry() but I am looking for something like GetProfile(). I don't see that function in Google API. Can you guide me on how to get UserProfiel?

    ReplyDelete
  3. Sorry, I want to try OAuth but I don't understand this post.
    Can u explain what is GoogleConsumer, what is DesktopConsumer? is it available in DotNetOpenAuth? or we have to create it by ourself? And where is the code?

    ReplyDelete