Overview
Providing the option of OpenID for account creation and sign-in helps keeps things easy on your users. It may even lower the barrier to people signing up for (and continuing to use) your service.
Authlogic implements user authentication beautifully, and it is readily extensible. By way of illustrating how to extend Authlogic, its author, Ben Johnson, released Authlogic OpenID. That makes supporting OpenID authentication as clean, easy, and flexible as Authlogic makes user authentication.
The difficulty, up to this point, has been testing OpenID. Some time ago, I was looking for ways to test OpenID, and I happened upon the Ruby OpenID Test Server (ROTS), by Román González. Googling various combination of ROTS and OpenID or Rails, one would think the experiment had failed, because of the lack of mention and its author’s only two blog posts on the topic [1] [2]. But I contacted Román via Git, and he offered very helpful assistance and pointed me to the rots_consumer, which is an example Rails (and Merb) application that uses ROTS to test OpenID. Today, I followed Román’s instructions and now have operational OpenID scenarios in my Cucumber suite (I was inspired to do so today because I wanted to add another OpenID related feature, and felt dirty not being able to do BDD).
This post covers how to get OpenID working in Cucumber (I’m running Cucumber 0.6.1, Cucumber-Rails 0.2.3, and Rails 2.3.5).
Details
To quote its ReadMe, “ROTS is a minimal implementation of an OpenID server.” When running OpenID tests against ROTS, the ROTS server must be running locally. It seems pretty lightweight, so isn’t a big deal, but if you don’t want to run against it all the time, tag your Cucumber scenarios that involve OpenID (or an entire file) with @openid and include “–tags ~@openid” as one of the std_opts in config/cucumber.yml. Then, when you want to test OpenID, run
$ cucumber --tags @openid features
Setting up your application to work with ROTS is pretty easy. First get ROTS. Román’s version is here. I ran into a problem in his current version with an application that requests dob from the OpenID server, so I wrote a patch. If you request dob as part of your OpenID request, check to see whether Román’s repository has fixed that issue, or use my fork. Either way, clone ROTS to your local system.
Once you have ROTS locally, build, install, and run the gem:
$ cd rots
$ gem build rots.gemspec
$ sudo gem install rots-0.2.2.gem
$ rots
I changed my default Screen settings to include a rots window and automatically launch rots. That way, I always have rots running when I open my work environment:
screen -t rots /bin/bash -c 'rots'
As an aside, I’m running Ubuntu 9.10, which comes with an elegant version of Screen called Byobu. Byobu makes it easy to set all the Screen preferences, such as changing ctrl-a to ctrl-j (not only is this better for Emacs, but J is the rest position for the right index finger, so is very fast).
Now for your Rails app.
Create features/support/openid.rb with the following contents:
require "rots"
World(Rots::TestHelper)
And features/step_definitions/openid_steps.rb with the following:
Then /^I (?:should )?receive a response from the OpenID Server$/ do
server_request_uri = response.headers['Location']
hash = openid_request(server_request_uri)
visit(hash[:url], :get, hash[:query_params])
end
At this point, you can write your Cucumber scenarios. The important step to remember is, after any successful call to the OpenID server, you must have the line
And I receive a response from the OpenID Server
or
Then I should receive a response from the OpenID Server
Here are the OpenID steps I implemented for one application:
http://gist.github.com/334789