4 Provides a thin wrapper around the excellent ruby-openid gem from JanRan. Be sure to install that first:
 
   6   gem install ruby-openid
 
   8 To understand what OpenID is about and how it works, it helps to read the documentation for lib/openid/consumer.rb
 
  11 The specification used is http://openid.net/specs/openid-authentication-2_0.html.
 
  17 OpenID authentication uses the session, so be sure that you haven't turned that off.
 
  19 Alternatively, you can use the file-based store, which just relies on on tmp/openids being present in RAILS_ROOT. But be aware that this store only works if you have a single application server. And it's not safe to use across NFS. It's recommended that you use the database store if at all possible. To use the file-based store, you'll also have to add this line to your config/environment.rb:
 
  21   OpenIdAuthentication.store = :file
 
  23 This particular plugin also relies on the fact that the authentication action allows for both POST and GET operations.
 
  24 If you're using RESTful authentication, you'll need to explicitly allow for this in your routes.rb.
 
  26 The plugin also expects to find a root_url method that points to the home page of your site. You can accomplish this by using a root route in config/routes.rb:
 
  28   map.root :controller => 'articles'
 
  30 This plugin relies on Rails Edge revision 6317 or newer.
 
  36 This example is just to meant to demonstrate how you could use OpenID authentication. You might well want to add
 
  37 salted hash logins instead of plain text passwords and other requirements on top of this. Treat it as a starting point,
 
  40 Note that the User model referenced in the simple example below has an 'identity_url' attribute. You will want to add the same or similar field to whatever
 
  41 model you are using for authentication.
 
  43 Also of note is the following code block used in the example below:
 
  45   authenticate_with_open_id do |result, identity_url|
 
  49 In the above code block, 'identity_url' will need to match user.identity_url exactly. 'identity_url' will be a string in the form of 'http://example.com' -
 
  50 If you are storing just 'example.com' with your user, the lookup will fail.
 
  52 There is a handy method in this plugin called 'normalize_url' that will help with validating OpenID URLs.
 
  54   OpenIdAuthentication.normalize_url(user.identity_url)
 
  56 The above will return a standardized version of the OpenID URL - the above called with 'example.com' will return 'http://example.com/'
 
  57 It will also raise an InvalidOpenId exception if the URL is determined to not be valid.
 
  58 Use the above code in your User model and validate OpenID URLs before saving them.
 
  62   map.root :controller => 'articles'
 
  66 app/views/sessions/new.erb
 
  68   <% form_tag(session_url) do %>
 
  70       <label for="name">Username:</label>
 
  71       <%= text_field_tag "name" %>
 
  75       <label for="password">Password:</label>
 
  76       <%= password_field_tag %>
 
  84       <label for="openid_identifier">OpenID:</label>
 
  85       <%= text_field_tag "openid_identifier" %>
 
  89       <%= submit_tag 'Sign in', :disable_with => "Signing in…" %>
 
  93 app/controllers/sessions_controller.rb
 
  94   class SessionsController < ApplicationController
 
  97         open_id_authentication
 
  99         password_authentication(params[:name], params[:password])
 
 105       def password_authentication(name, password)
 
 106         if @current_user = @account.users.authenticate(params[:name], params[:password])
 
 109           failed_login "Sorry, that username/password doesn't work"
 
 113       def open_id_authentication
 
 114         authenticate_with_open_id do |result, identity_url|
 
 115           if result.successful?
 
 116             if @current_user = @account.users.find_by_identity_url(identity_url)
 
 119               failed_login "Sorry, no user by that identity URL exists (#{identity_url})"
 
 122             failed_login result.message
 
 130         session[:user_id] = @current_user.id
 
 131         redirect_to(root_url)
 
 134       def failed_login(message)
 
 135         flash[:error] = message
 
 136         redirect_to(new_session_url)
 
 142 If you're fine with the result messages above and don't need individual logic on a per-failure basis,
 
 143 you can collapse the case into a mere boolean:
 
 145     def open_id_authentication
 
 146       authenticate_with_open_id do |result, identity_url|
 
 147         if result.successful? && @current_user = @account.users.find_by_identity_url(identity_url)
 
 150           failed_login(result.message || "Sorry, no user by that identity URL exists (#{identity_url})")
 
 156 Simple Registration OpenID Extension
 
 157 ====================================
 
 159 Some OpenID Providers support this lightweight profile exchange protocol.  See more: http://www.openidenabled.com/openid/simple-registration-extension
 
 161 You can support it in your app by changing #open_id_authentication
 
 163       def open_id_authentication(identity_url)
 
 164         # Pass optional :required and :optional keys to specify what sreg fields you want.
 
 165         # Be sure to yield registration, a third argument in the #authenticate_with_open_id block.
 
 166         authenticate_with_open_id(identity_url,
 
 167             :required => [ :nickname, :email ],
 
 168             :optional => :fullname) do |result, identity_url, registration|
 
 171             failed_login "Sorry, the OpenID server couldn't be found"
 
 173             failed_login "Sorry, but this does not appear to be a valid OpenID"
 
 175             failed_login "OpenID verification was canceled"
 
 177             failed_login "Sorry, the OpenID verification failed"
 
 179             if @current_user = @account.users.find_by_identity_url(identity_url)
 
 180               assign_registration_attributes!(registration)
 
 185                 failed_login "Your OpenID profile registration failed: " +
 
 186                   @current_user.errors.full_messages.to_sentence
 
 189               failed_login "Sorry, no user by that identity URL exists"
 
 195       # registration is a hash containing the valid sreg keys given above
 
 196       # use this to map them to fields of your user model
 
 197       def assign_registration_attributes!(registration)
 
 198         model_to_registration_mapping.each do |model_attribute, registration_attribute|
 
 199           unless registration[registration_attribute].blank?
 
 200             @current_user.send("#{model_attribute}=", registration[registration_attribute])
 
 205       def model_to_registration_mapping
 
 206         { :login => 'nickname', :email => 'email', :display_name => 'fullname' }
 
 209 Attribute Exchange OpenID Extension
 
 210 ===================================
 
 212 Some OpenID providers also support the OpenID AX (attribute exchange) protocol for exchanging identity information between endpoints.  See more: http://openid.net/specs/openid-attribute-exchange-1_0.html
 
 214 Accessing AX data is very similar to the Simple Registration process, described above -- just add the URI identifier for the AX field to your :optional or :required parameters.  For example:
 
 216         authenticate_with_open_id(identity_url,
 
 217             :required => [ :email, 'http://schema.openid.net/birthDate' ]) do |result, identity_url, registration|
 
 219 This would provide the sreg data for :email, and the AX data for 'http://schema.openid.net/birthDate'
 
 223 Copyright (c) 2007 David Heinemeier Hansson, released under the MIT license