At the Forge - Integrating OpenID

 in
Integrate OpenID into any Rails application, using off-the-shelf libraries and a bit of custom code.
Storing User Information

When we display this form in our browser, the user has one option—namely, to sign in with OpenID by entering a URL. The action (create) that is invoked has to find the user's OpenID server and redirect to that server. In order to do this, we need an instance of OpenID::Consumer, an object defined by the ruby-openid gem. Because we will continue to need this, we can create it as an instance variable:

def openid_consumer
 if @openid_consumer.blank?
   @openid_consumer =
     OpenID::Consumer.new(session,
           OpenID::Store::Filesystem.new("#{RAILS_ROOT}/tmp/openid"))
 end

 return @openid_consumer
end

Notice that we're storing the OpenID information on the filesystem, in the tmp directory under the root of our Rails project directory. This is a bad idea when you have multiple Web servers, but is certainly good enough for a small or beginning site.

Now that we have a method named openid_consumer and an instance variable named @openid_consumer, we can implement the create action, to which our HTML form is going to be submitted:

def create
 # Get the OpenID parameter
 openid_url = params[:openid_url]

 # Make sure we got something
 if openid_url.blank?
   flash[:error] = "No OpenID was entered; try again"
   redirect_to :back
   return
 end

 # Get an OpenID response
 openid_response = openid_consumer.begin openid_url

 home_url = url_for :controller => "openid", :action => "index"
 complete_url = url_for :controller => "openid", :action => "complete"
 openid_redirect_url = openid_response.redirect_url(home_url, complete_url)
 redirect_to openid_redirect_url

 return
end

In other words, we get the user's OpenID URL, and we check that it wasn't blank. Then, we use our instance of OpenID::Consumer to begin the OpenID login process, using open_consumer.begin, passing it the user's OpenID URL. If all goes well, this returns an instance of SuccessRequest, which also hands us the URL to which we should redirect the user. (If the request fails, the response will be a subclass of OpenIDStatus.)

Completing the Login Process

When we send the user to the user's OpenID server, we have to provide two different URLs as arguments: one that we're calling home_url, and the other that we're calling complete_url. The former is the root URL of our site; typically, it'll be a top-level URL. The latter, complete_url, tells the OpenID server to which URL the user should be redirected after logging in. In both cases, I use the built-in Rails url_for method, which constructs a URL out of a controller and action name.

When the user returns from the OpenID server, it will be to the URL indicated in complete_url. This means we have to define our complete method as well:

def complete
 home_url = url_for :controller => "openid", :action => "index"
 complete_url = url_for :controller => "openid", :action => "complete"

 openid_response = openid_consumer.complete(params, complete_url)

 session[:openid] = openid_response.identity_url
 flash[:error] = "You have been logged in as '#{session[:openid]}'"
 redirect_to :action => "new"
 return
end

After defining home_url and complete_url once again, we invoke the complete method on our instance of OpenID::Consumer. If the response is good (and here we assume that it is, ignoring the possibility that we might have gotten an instance of OpenIDStatus back). Obviously, your real-life applications should include such a check.

Sure enough, when we put all this in place, it works! We can enter our user ID into the HTML form. We get verified by the user's OpenID server, even if that means another redirect. And, we get the user verified with basic information.

______________________

White Paper
Linux Management with Red Hat Satellite: Measuring Business Impact and ROI

Linux has become a key foundation for supporting today's rapidly growing IT environments. Linux is being used to deploy business applications and databases, trading on its reputation as a low-cost operating environment. For many IT organizations, Linux is a mainstay for deploying Web servers and has evolved from handling basic file, print, and utility workloads to running mission-critical applications and databases, physically, virtually, and in the cloud. As Linux grows in importance in terms of value to the business, managing Linux environments to high standards of service quality — availability, security, and performance — becomes an essential requirement for business success.

Learn More

Sponsored by Red Hat

White Paper
Private PaaS for the Agile Enterprise

If you already use virtualized infrastructure, you are well on your way to leveraging the power of the cloud. Virtualization offers the promise of limitless resources, but how do you manage that scalability when your DevOps team doesn’t scale? In today’s hypercompetitive markets, fast results can make a difference between leading the pack vs. obsolescence. Organizations need more benefits from cloud computing than just raw resources. They need agility, flexibility, convenience, ROI, and control.

Stackato private Platform-as-a-Service technology from ActiveState extends your private cloud infrastructure by creating a private PaaS to provide on-demand availability, flexibility, control, and ultimately, faster time-to-market for your enterprise.

Learn More

Sponsored by ActiveState