Step-by-Step Guide to Integrating OpenAuth into Your Rails Application

Enable the Subscriptions block here!

Part of the OpenAuth Web Integration Series

by Jack Herrington
September 21 2007

Download a Printable Version

No matter what kind of Web application you build, the process always seems to start in the same place: managing user accounts. Writing a file-sharing application for the Web? You begin by identifying who is uploading the file. Writing a chat application for the Web? You have to know who will use the chat session, so you can give them access. Because the Web is inherently multi-user, any application you build is going to require managing a list of users.

For Rails programmers, this means one of several approaches:

  • Use the LoginGenerator gem – The login generator does a good job of building a user infrastructure for you. But it’s still something you have to maintain, upgrade, and potentially bug-fix. In addition, your customers will still have to use a separate user name and password to access your Web service.
  • Roll your own – You could build it yourself by creating a table of users, building the data accessors, encrypting the passwords, and all that back-end stuff. Then you have to create an interface for logging in, requesting passwords, sending e-mails, and so on. To do it right is a lot of work.
  • Use an example – You could use an example set of code like the one in the Ruby Cookbook by O'Reilly. But it’s still just a starting point. It doesn’t offer password recovery or any of the features that you need in a production application.
  • Use an identity provider – The last option (and not coincidently the point of this article) is to use an external identity provider. In this case, I’ll show you how using the AOL Open Authentication API (OpenAuth).

Using an external identity provider offers a lot of advantages, not just to you, the application developer, but also to your customers. You get to start building your application right away, confident that you will be able to identify users and log them in quickly and reliably. And your customers will be able to reuse their existing user names and passwords. Of course, that depends on the popularity of the identity provider; in the case of AOL this means leveraging the millions of people who have already registered with AOL Instant Messaging (AIM), among the many services AOL offers.

Getting an Account

Getting started with the AOL OpenAuth system is remarkably easy. The first step is to get an AOL account. They are free, so this is easily done. The next step is to get a developer ID (devId) for your AOL account. To do this we start at the OpenAuth home page. Then click the Getting Started link toward the top of the page to continue.

Click the AOL Developer Site link to see a list of devIds associated with your account, if any.

Click the Create new devId link to access the devId request form.

On this form enter your first and last name, your e-mail address, and then, most importantly, the URL where your customers should be redirected after a successful login. When you have this information filled in, submit the form and you should see results similar to the following:

The Id field is the important one here. It is the ID you will use on the login page in your Web application.

The OpenAuth Page Flow

With the devId set up, let's take a step back and figure out how the login page flow is going to work in your application. The following screen shot shows the page flow when the customer is not logged in to an AOL account.

The customer first goes to the "index" action of your login controller. Because they have not yet logged in they click a link to go to the AOL login page. There they type their AOL screen name and password. If it’s valid, they are redirected to the login controller through URL-based arguments that encode the user name of the customer.

To complete the login the "index" action that receives the URL parameters from AOL needs to go back to the AOL OpenAuth site to get your account information. This is done using the standard Net::HTTP library. The customer doesn’t see the request. The customer's user name appears in the application courtesy of the GetInfo call, which returns the user name from AOL. In addition to GetInfo you can make calls to see if someone is currently logged in to AOL, or log them off.

If the customer is already logged in, OpenAuth bypasses the login page.

This means that customers can log in to your site without retyping their AOL screen name and password, if they are already logged into AOL. An extra advantage for free!

If you intend to use AOL exclusively as your user management system you could bypass the initial link on the "index" action by forwarding the customer directly to the AOL login page if they have not yet logged in.

Building the Login Page

Although the page flow might look complex, the actual Ruby code that manages the OpenAuth login is remarkably simple. The entire Ruby code for the login controller is shown in Listing 1.

Listing 1. Login_controller.rb

class LoginController < ApplicationController def index login_url = 'http://localhost:3004/login' devId = '** Your DevID **' if ( params['token_a'] ) aol_info = 'http://api.screenname.aol.com/auth/getInfo?f=qs' aol_info += '&devId='+devId+'&a='+CGI::escape( params['token_a'] ) aol_info += '&referer='+CGI::escape(login_url) data = Net::HTTP.get( URI.parse aol_info ) data.scan( /&userData_loginId=(.*?)&/ ) session[:user] = $1 @logged_in = true else @aol_login_url = 'http://api.screenname.aol.com/auth/login?f=qs' @aol_login_url += '&devId='+devId+'&supportedIdType=SN,ICQ,OID' @aol_login_url += '&succUrl='+CGI::escape(login_url) @logged_in = false end render end end

All you need to do is change the login_url and devId variables to the URL for your site and your developer ID, respectively.

The code first looks for the URL arguments returned from AOL to see if the customer is being sent back after a successful login. If that’s the case, the user name is set to whatever is returned by the GetInfo call. If the URL arguments are not set, this is likely the first time the customer has seen the page, so they are given the login link.

The ERb template for the index page is shown in Listing 2.

Listing 2. Index.rhtml

<html> <body> <% if @logged_in %> You have successfully logged with your ID: <%= session[:user] %><br/> <%= link_to "home", { :controller => 'login', :action => 'home' } %> <% else %> Use your AOL/AIM ID, ICQ Account or OpenId url to <a href="<%= @aol_login_url %>">Login</a> <% end %> </body> </html>

There are two versions of this page: one that is shown when the user is logged in, and one when they are not. If the user is logged in they get a link to the "home" action. If they are not logged in they are get a link to the AOL login page.

To demonstrate this I’ll use my browser to go to the "index" action of the login controller.

It’s not much to look at, but it works. Here I click the Login link, which takes me to the AOL login page. This is where the customer logs in to their AIM, ICQ, or OpenID account.

After I click Sign In, assuming the credentials are correct, I am returned to my home page, logged in.

How easy is that, right? Now I have a complete user management system for my application in just--what, 20?--lines of Ruby and a little RHTML? Pretty sweet. And my customers get to use their AIM accounts to log in, so they don’t have to remember yet another account name and password to access my Web service.

The home page for the user is very simple and easy to use. It shows the screen name of the person who is logged in, and provides a link to the user's AIM buddy list.

Listing 3. Home.rhtml

<html> <head> <script type="text/javascript" src="http://o.aolcdn.com/aim/web-aim/aimapi.js"></script> </head><body> <table width="100%"><tr><td valign="top"> User: <%= session[:user] %> </td><td valign="top"> <div id="AIMBuddyListContainer" wim_key="** Your WIM Key **"></div> <a onclick="AIM.widgets.buddyList.launch();return false;" href="nojavascript.html">Launch my Buddy List</a> </td></tr></table> </body> </html>

Most of the code here is to support the buddy list. At the top I include the Aimapi.js file from AOL, which contains the code for the AIM widgets. Below I put in a buddy list container <div> and an anchor tag that has Javascript to launch the widget.

You can see this in action after I have logged in.

You don’t need to have the buddy list to get this to work. This is just an example of how you can use some of the other AOL APIs to enhance what customers can do on your site.

Going On from Here

This isn't the only service that AOL offers. AOL is opening APIs and technologies from identity to instant messaging, media and community, and providing Web application developers with a wide range of scalable solutions. In addition to the Web AIM widgets, AOL has a file-hosting service called OpenXdrive that you can use to host image or movie files, the same way developers are using Amazon's Simple Storage Service (Amazon S3) Web service. AOL has a video-sharing service similar to YouTube, and an industry-leading video search engine called Truveo. MapQuest maps can be integrated into your page. All the currently available AOL Open APIs, and associated documentation, are at http://dev.aol.com/apis. AOL is really opening up and this article shows you how easily AOL APIs can be integrated into your applications.

Conclusion

Even if you don’t want to use OpenAuth as your identity management system, this API presents an easy way to give users access to your service with minimal hassle. And if you want to use it as your user management system, you get a very easy-to-use API for free. It’s definitely worth your time to look into using OpenAuth on your site. That way you get to concentrate of the fun features that make your site interesting and avoid the hassle of reimplementing user account and password maintenance features for the umpteenth time.