steverb.com

Things I Felt Like Posting

Fun With OAuth - Part 1

We’ve been working on implementing some sort of enterprise wide single sign-on (SSO) at work. As part of that we really needed some way to authenticate with web services without depending on Windows or Basic Authentication, which is a phenomenal pain in the butt.

Enter OAuth

OAuth is “An open protocol to allow secure API authorization in a simple and standard method from desktop and web applications.” In other words, you can authenticate with it from lots of different places.

The way full blown OAuth works is that you use an application that wants to access your data that resides in another service or application. The application wanting the data sends you to the authentication site for the service that has your data. You login, and then tell the service that you will allow the app to access your data. The service sends you back to the application with a request key. The application sends the request key to the service and the service sends the application an access key.

Once all that handshaking is done, the application takes the consumer secret and the consumer key (that the application already had) along with the recently obtained access key and a few other relevant pieces of info (timestamp, nonce, etc) and hashes them all together. The application then takes all this information and creates an OAuth header that it sends with any service requests. The service then uses the information in the header to identify the application acting on behalf of the user.

It sounds complicated because it kinda is, but once you’ve run through it a few times it starts to make sense. I suggest you read The Beginner’s Guide to OAuth to get a thorough understanding.

Why would you do this to yourself?

The really nice thing about OAuth is that it works on a lot of platforms. There are implementations in C#, there are implementations in Ruby, there are implementations in Javascript. Awesome. So let’s use it.

Here, have some Javascript:

   1: function getHello(mToken, mWord)
   2: {
   3:    //create the message portion
   4:     var message = {
   5:         method: "GET",
   6:         action: url,
   7:         parameters: {oauth_version: "1.0",
   8:         oauth_consumer_key: "myservicekey",
   9:         oauth_timestamp: OAuth.timestamp(),
  10:         oauth_nonce: OAuth.nonce(11),
  11:         oauth_signature_method: "HMAC-SHA1"                        
  12:         }
  13:     };
  14:  
  15:  
  16:     //create the accessor portion   
  17:     var accessor = {
  18:         consumerSecret: "myappssecretkey"
  19:         tokenSecret: "theSecretIGoFromTheUserSigningIn"
  20:     };
  21:    
  22:     //sign the OAuth message
  23:     OAuth.SignatureMethod.sign(message, accessor);
  24:    
  25:     //generate the entire header (with signature included)
  26:     var authorizationHeader = OAuth.getAuthorizationHeader("", message.parameters);
  27:     
  28:     //make the ajax call
  29:     $.ajax(
  30:     {
  31:         //set the OAuth authorization header before we send the web request
  32:         beforeSend: function(req) 
  33:         {
  34:             req.setRequestHeader("Authorization", authorizationHeader);
  35:          },
  36:          type: "GET",
  37:          url: "http://myservice.com/Hello?World=" + mWord,
  38:          contentType: "text/plain; charset=utf-8",
  39:          dataType: "text",
  40:          success: function(data) {
  41:              $("#ingest_history").html("The REST Service said: " + data);
  42:          }
  43:     });
  44: }
  45:        


Here we have an example of calling a web service with OAuth. Now, what’s the service going to do with it?

The service is going to do the same thing. It’s going to take the publicly readable information in the header, and combine that with the secrets that it knows and make sure they match. I’ll post the code to do that next time.

Comments (8) -

  • Stever B

    3/15/2010 3:50:28 AM | Reply

    I will also post calling an OAuth service using C# next time too. Didn't have time to fit it in this post.

  • Daniel Brown

    3/15/2010 9:11:49 AM | Reply

    I don't know if we've got our security model nailed down on our new platform, but this looks like something I might could pass to our developers.  Cool, Steve!

  • Neville

    3/15/2010 3:15:32 PM | Reply

    'Nonce?' I had no idea OAuth was a sex offender...har

  • Bruce Boughton

    4/6/2010 4:14:56 AM | Reply

    Nice post. Is your JavaScript example intended to run client-side or server-side? If it's client side, then you should be careful--you're embedding your consumer secret in your JavaScript which makes it publicly visible. This significantly affects the security of using the OAuth protocol. In a real implementation, you do really need some secure server-side storage for the secrets involved in the OAuth 'handshake'. Essentially, you need to proxy your AJAX calls via a server-side proxy to perform the OAuth signing.

    Incidentally, the .NET implementation you link to isn't really a full implementation--it's basically a small part of doing OAuth authentication. There are some complete .NET OAuth libraries available, for example http://code.google.com/p/oauth-dot-net (disclaimer: I am one of the authors of this open source library).

  • Stever B

    4/6/2010 5:05:59 AM | Reply

    Thanks Bruce. I'll definitely check that one out.

    And yes, the javascript is client side and it is a security risk. There are ways to mitigate the risk though, such as making all of the keys one time use only.

  • Neville

    5/26/2010 3:40:23 AM | Reply

    That's funny, you need to implement OAuth on yer OAuth blog post to keep out the "Adidas Spammer"

  • Stever B

    5/26/2010 4:27:17 AM | Reply

    Yeah, he snuck through my filter last night. Blacklisted now.

  • Stever b

    5/26/2010 9:15:27 PM | Reply

    Spammers have been all over this post today...hard to stay on top of them.

Loading