Open ID Authentication

Provides a thin wrapper around the excellent ruby-openid gem from JanRan. Be sure to install that first:

gem install ruby-openid

To understand what OpenID is about and how it works, it helps to read the documentation for lib/openid/consumer.rb from that gem.

Prerequisites

OpenID authentication uses the session, so be sure that you haven’t turned that off. It also relies on tmp/openids being present in RAILS_ROOT. The install.rb should install that automatically as you get the plugin, but if not, be sure to do that yourself.

This particular plugin also relies on the fact that the authentication action allows for both POST and GET operations. If you’re using RESTful authentication, you’ll need to explicitly allow for this in your routes.rb.

Example

This example is just to meant to demonstrate how you could use OpenID authentication. You’ll might well want to add salted hash logins instead of plain text passwords and other requirements on top of this. Treat it as a starting point, not a destination.

config/routes.rb
1 map.open_id_complete 'session', :controller => "session", :action => "create", :requirements => { :method => :get }
2   map.resource :session
app/controllers/session_controller.rb
 1 class SessionController < ApplicationController
 2     def create
 3       if open_id?(params[:name])
 4         open_id_authentication(params[:name])
 5       else
 6         password_authentication(params[:name], params[:password])
 7       end
 8     end
 9 
10 
11     protected
12       def password_authentication(name, password)
13         if @current_user = @account.users.find_by_name_and_password(params[:name], params[:password])
14           successful_login
15         else
16           failed_login "Sorry, that username/password doesn't work"
17         end
18       end
19 
20       def open_id_authentication(identity_url)
21         authenticate_with_open_id(identity_url) do |status, identity_url|
22           case status
23           when :missing
24             failed_login "Sorry, the OpenID server couldn't be found"
25           when :canceled
26             failed_login "OpenID verification was canceled"
27           when :failed
28             failed_login "Sorry, the OpenID verification failed"
29           when :successful
30             if @current_user = @account.users.find_by_identity_url(identity_url)
31               successful_login
32             else
33               failed_login "Sorry, no user by that identity URL exists"
34             end
35           end
36         end
37       end
38     
39     
40     private
41       def successful_login
42         session[:user_id] = @current_user.id
43         redirect_to(root_url)
44       end
45 
46       def failed_login(message)
47         flash[:error] = message
48         redirect_to(new_session_url)
49       end
50       
51       # Set #root_url if your root url has a different named route.
52       #
53       #   map.home '', :controller => ..., :action => ...
54       #
55       # Otherwise, name the route 'root' and leave this method out.
56       def root_url
57         home_url
58       end
59   end

Simple Registration OpenID Extension

Some OpenID Providers support this lightweight profile exchange protocol. See more: http://www.openidenabled.com/openid/simple-registration-extension

You can support it in your app by changing #open_id_authentication
 1 def open_id_authentication(identity_url)
 2         # Pass optional :required and :optional keys to specify what sreg fields you want.
 3         # Be sure to yield registration, a third argument in the #authenticate_with_open_id block.
 4         authenticate_with_open_id(identity_url, :required => [:nickname, :email], :optional => :fullname) do |status, identity_url, registration|
 5           case status
 6           when :missing
 7             failed_login "Sorry, the OpenID server couldn't be found"
 8           when :canceled
 9             failed_login "OpenID verification was canceled"
10           when :failed
11             failed_login "Sorry, the OpenID verification failed"
12           when :successful
13             if @current_user = @account.users.find_by_identity_url(identity_url)
14               # registration is a hash containing the valid sreg keys given above
15               # use this to map them to fields of your user model
16               {'login=' => 'nickname', 'email=' => 'email', 'display_name=' => 'fullname'}.each do |attr, reg|
17                 current_user.send(attr, registration[reg]) unless registration[reg].blank?
18               end
19               unless current_user.save
20                 flash[:error] = "Error saving the fields from your OpenID profile: #{current_user.errors.full_messages.to_sentence}"
21               end
22               successful_login
23             else
24               failed_login "Sorry, no user by that identity URL exists"
25             end
26           end
27         end
28       end

Tags

You need to Login to tag this item.