Over the past few months I’ve gotten increasingly interested in REST services. Maybe it’s the beautiful simplicity of the concept, or the fact that I can get obsessive about things like URL schemas and HTTP verb usage, but the technology has really gotten my attention. In addition to spending way too much time reading about the merits of POST v. PUT when uploading content, or when you should (or shouldn’t) put the version number of your API in the URL, I’ve also gotten into in authentication and authorization of requests.
Software security in general has always been a topic that interest me enough to want to read up and self-educate, but I’ll also admit to never being too interested in all the gory details. So while working on the REST API that I’ve been playing with at work, I was hoping to find something that would satisfy the following authentication/authorization requirements:
- making sure the calling user is who they say they are
- having some piece of data that uniquely identifies the calling user
- supporting multiple authentication services (Live ID, Yahoo, Google, etc)
I couple of months ago I did some initial reading on OAuth which looked rather promising, but then when attending a session on OAuth at Web 2.0 in San Francisco, I go scared away from the technology when the speaker said something to the effect of “OAuth should be killed”, not a ringing endorsement from someone who was much more knowledgeable about the technology. I looked into Facebook Connect a little, then someone at work told me about Windows Azure Access Control Service (ACS). A quick read through some docs on the codeplex site and other sources on the web had me intrigued. Not being one to read lots of documentation (or instructions in general) I jumped into trying to integrate ACS into my REST API, which comprises of read/write operations for files and has some minimal user management capabilities too.
The results are promising. Once I got my head wrapped around the various components and their levels of interaction (which are described in the sequence diagrams on the codeplex site), the integration with my service wasn’t too painful although I did find that the web examples were a little lacking, specifically around browser (HTML/Javascript) based clients interacting with a site or service that is using ACS for authentication + authorization. After some experimenting, I got the whole thing work by doing the following (I may end up posting the code at some point if there’s interest, but hopefully a description is good enough for starters):
- Creating a new Access Control Namespace (done via the Azure Management site)
- Configuring the new Access Control Namespace for my service
- Picking the identity providers that I wanted to use (Live ID, Yahoo and Google)
- Adding my service as a Relying Party Application
- Configuring my service’s Relying Party Application settings, which includes:
- Setting the Realm and Return URL’s (I used the default.aspx page for both, this is where ACS will re-direct the browser to upon completion of authentication via the identity provider and authorization token minting via ACS).
- Setting the Token format (I used SWT since it’s a little more web-friendly due to it being plain text and not XML)
- Setting the Rule groups (this is where I tell ACS what I want it to add to the SWT token that comes back to my service upon successful authentication)
- Setting the Token Signing Key (will need this in my application to enable it to decrypt the SWT token that ACS passes back upon successful authentication)
- Adding a link from my site to an ACS hosted page that allows the user to select their preferred authentication provider and then re-directs the user to the providers login page. The ACS management page generates this link in the Development -> Application Integration page, just copy/past the link into a page on your site and ACS does the rest.
- Adding parts of the shared code (that’s in the Management\ManagementService\Common directory of the downloadable sample code from codeplex)
- Gets SWT token in the incoming request
- Saves the SWT token in cookie to make it accessible to subsequent requests on my service
- Checks for authorization status in the SWT token, a token contains valid authorization status if it has:
- The same HMAC signature that was generated by ACS when it was encrypted (this is where my service code needs the Token Signing Key)
- Non-expired data
- The issuer is trusted (this is configured in my service code)
- The audience is trusted (this is configured in my service code)
With all of this, I have a WCF REST service that leverages ACS as the authentication/authorization provider. I have the code setup to allow un-authenticated reads but require authentication + authorization on writes. I can let users use either of Live ID, Google or Yahoo for login support (to minimize the chances of needing to sign up for a new login account) and can get the user’s email address, which I use as a means of identifying users internally, from the SWT token that comes back, pretty cool stuff!