OpenID Single Sign-On
by Jeremy Weiskotten


Example 1: Creating and destroying sessions

def create
  open_id_authentication
end
def destroy
  reset_session
  self.current_user = nil
  flash.now[:notice] = 'You have logged out.'
  render :action => 'new'
end

Example 2: OpenID Authentication

def open_id_authentication
  if params[:openid_url].blank? && params[:open_id_complete].blank?
    return failed_login("Please enter your OpenID")
  end
  @openid_url = params[:openid_url]
  # Pass optional :required and :optional keys to specify what sreg fields 
  # you want. Be sure to yield registration, a third argument in the block.
  authenticate_with_open_id(@openid_url, 
      :required => [:email],
      :optional => [:dob, :fullname]
      ) do |result, identity_url, registration|

    if result.successful?
      user = User.find_by_identity_url(identity_url)
      if user.nil?
        user = User.new
        user.identity_url = identity_url
      
        unless assign_registration_attributes(user, registration)
         return failed_login("Your OpenID registration failed: " +
            user.errors.full_messages.to_sentence)
        end
      end
      self.current_user = user
      successful_login
    else
      failed_login(result.message || "Sorry, could not authenticate 
        #{identity_url}")
    end
  end
end


Example 3: Handling a login failure (app/controllers/session_controller.rb)

def failed_login(message)
  flash.now[:error] = message
  render :action => 'new'
end

Example 4: Assigning sreg attributes to a new user

# Maps OpenID sreg keys to fields of your user model.
# registration is a hash containing valid sreg keys
def assign_registration_attributes(user, registration)
  { 
    :email => 'email', 
    :date_of_birth => 'dob', 
    :full_name => 'fullname' 
  }.each do |model_attr, registration_attr|
    unless registration[registration_attr].blank?
      user.send "#{model_attr}=", registration[registration_attr]
    end
  end
  user.save
end

Example 5: Managing the current user's session

class ApplicationController < ActionController::Base
  helper_method :current_user
  protected
  # Accesses the current user from the session.
  def current_user
    @current_user ||= 
      (session[:user_id] && User.find_by_id(session[:user_id]))
  end
  # Store the given user in the session.
  def current_user=(new_user)
    session[:user_id] = new_user && new_user.id
    @current_user = new_user
  end     
end


Example 6: Handling a successful login

def successful_login
  redirect_to :controller => 'welcome'
end


Example 7: Login form (app/views/session/new.html.erb)

<% form_tag session_path do -%>
<dl class="form">
     <dt><label for="openid_url">OpenID</label></dt>
     <dd><%= text_field_tag "openid_url", @openid_url, :size => 30 %></dd>
     <dd><%= submit_tag 'Log in', :disable_with => "Logging in&hellip;" %></dd>
</dl>
<% end -%>


Example 8: Welcome! (app/views/welcome/index.html.erb)

<p>
     Your OpenID identity URL is 
     <strong><%= current_user.identity_url %></strong>.
</p>

<p>
     <%= link_to 'Log out', logout_path %>
</p>

Example 9: Routes (config/routes.rb)

ActionController::Routing::Routes.draw do |map|
  map.login  'login',  :controller => 'session', :action => 'new'
  map.logout 'logout', :controller => 'session', :action => 'destroy'
  # You can have the root of your site routed with map.root -- 
  # just remember to delete public/index.html.
  map.root :controller => 'welcome', :action => 'index'
  map.open_id_complete 'session', :controller => 'session', 
    :action => 'create', :requirements => { :method => :get }
  map.resource :session
  # Install the default route as the lowest priority.
  map.connect ':controller/:action/:id.:format'
  map.connect ':controller/:action/:id'
end


3


