Ruby web sites and Windows Azure AppFabric Access Control

Recently I was trying to figure out how to allow users to login to a Ruby (Sinatra) web site using an identity service such as Facebook, Google, Yahoo, etc. I ended up using Windows Azure AppFabric Access Control Service (ACS) since it has built-in support for:

Facebook

Google

Yahoo

Windows Live ID

WS-Federation Identity Providers

The nice thing is that you can use one or all of those, and your web application just needs to understand how to talk to ACS and not the individual services. I worked up an example of how to do this in Ruby, and will explain it after some background on ACS and how to configure it for this example.

What is ACS?

ACS is a claims based, token issuing provider. This means that when a user authenticates through ACS to Facebook or Google, that it returns a token to your web application. This token contains various ‘claims’ as to the identity of the authenticating user.

The tokens returned by ACS are either simple web tokens (SWT) or security assertion markup language (SAML)1.0 or 2.0. The token contains the claims, which are statements that the issuing provider makes about the user being authenticated.

The claims returned may, at a minimum, just contain a unique identifer for the user, the identity provider name, and the dates that the token is valid. Additional claims such as the user name or e-mail address may be provided – it’s up to the identity provider as to what is available. You can see the claims returned for each provider, and select which specific ones you want, using the ACS administration web site.

Configuring ACS

To configure ACS, you’ll need a Windows Azure subscription. Sign in at http://windows.azure.com, then navigate to the “Service Bus, Access Control & Caching” section. Perform the following tasks to configure ACS:

Using the ribbon at the top of the browser, select “New” from the Service Namespace section.

In the “Create a new Service Namespace” dialog, uncheck Service Bus and Cache, enter a Namespace and Region, and then click the Create Namespace button.

Select the newly created namespace, and then click the Access Control Service icon on the ribbon. This will take you to the management site for your namespace.

2: Relying Party Applications

This is your web application. Enter a name, Realm (the URL for your site,) the Return URL (where ACS sends tokens to,) error URL’s, etc. For token format you can select SAML or SWT. I selected SWT and that’s what the code I use below uses. You’ll need to select the identity providers you’ve configured. Also be sure to check “Create new rule group”. For token signing settings, click Generate to create a new key and save the value off somewhere.

3: Rule groups

If you checked off “Create new rule group” you’ll have a “Default Rule Group” waiting for you here. If not, click Add to add one. Either way, edit the group and click Generate to add some rules to it. Rules are basically how you control what claims are returned to your appication in the token. Using generate is a quick and easy way to populate the list. Once you have the rules configured, click Save.

4: Application Integration

In the Application Integration section, select Login pages, then select the application name. You’ll be presented with two options; a URL to an ACS-hosted login page for your application and a button to download an example login page to include in your application. For this example, copy the link to the ACS-hosted login page.

ACS with Ruby

The code below will parse the token returned by the ACS-hosted login page and return a hash of claims, or an array containing any errors encountered during validation of the token. It doesn't fail immediately on validation, as it may be useful to examine the validation failures to figure out any problems that were encountered. Also note that the constants need to be populated with values specific to your application and the values entered in the ACS management site.

get_element, which is used to pick out various pieces of the XML document.

parse_addres, expires, token_type, which pull out and validate the individual elements

parse_token, which decodes the binary token, validates it, and returns the claims collection.

After processing the token, you can test for validity by using is_valid? and then parse through either the claims hash or validation_errors array. I'll leave it up to you to figure out what you want to do with the claims; in my case I just wanted to know the identity provider the user selected and thier unique identifier with that provider so that I could store it along with my sites user specific information for the user.

Summary

As mentioned in the introduction, ACS let’s you use a variety of identity providers without requiring your application to know the details of how to talk to each one. As far as your application goes, it just needs to understand how to use the token returned by ACS. Note that there may be some claim information provided that you can use to gather additional information directly from the identity provider. For example, FaceBook returns an AccessToken claim field that you an use to obtain other information about the user directly from FaceBook.

As always, let me know if you have questions on this or suggestions on how to improve the code.

Thank you very much for the post! I just got this working correctly on a project that I'm working on in Rails. Before reading this (and being a Rails newb), I wasn't sure how to implement ACS in Rails. This gave me everything I needed!

Single sign-out with ACS is pretty easy. It's just doing a redirect to a specially crafted URL, which then does a GET back to a page on your web site. The URL format is https://<your namespace>.accesscontrol.windows.net/v2/wsfederation?wa=wsignout1.0&wtrealm=<your realm>&wreply=<return page>. The only trick is that the realm and return page values have to be encoded. For example, if my namespace is "mynamespace", my realm is "http://localhost", and the page I want users to land on once they have been signed out is "http://localhost/youareloggedout", then this would be mynamespace.accesscontrol.windows.net/.../wsfederation

That's it. What this does is log the user out of the services associated with ACS. If they don't log out, you see the behavior where they click the login link on your site, it redirects to ACS, then immediately back to your site without asking them to provide credentials for the identity provider. After hitting the sign-out URL above, the next time they login ACS should prompt them to select the identity provider and provide username/password for it.

Also, I'm told that Windows Azure Active Directory is now the way to go vs. ACS. I haven't worked with WAAD, so I don't currently have any recommendations or pointers for that. I'll see if I can work up a sample of using that and post to the blog.