restful_authentication snippets

How to install and use the restful_authentication Rails plugin

Tagged rails, ruby, authentication, restful_authentication  Languages ruby

This is an adaptation of the restful_authentication screencast by Ryan Bates, which has an issue with Rails 2.0.3 that throws the following error:

NameError (uninitialized constant SessionsController):
    /usr/local/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:266:in load_missing_constant'
    /usr/local/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:453:in const_missing'
    /usr/local/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:465:in const_missing'
    /usr/local/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/inflector.rb:257:in constantize'

Installing the restful_authentication plugin

script/plugin source http://svn.techno-weenie.net/projects/plugins/
script/plugin install restful_authentication

Generating the model and controller

script/generate authenticated user sessions

Now run the migration:

rake db:migrate

Configure routing

Open config/routes.rb and add the following routes:

map.resources :users
map.resource  :session

map.signup '/signup', :controller => 'users', :action => 'new'
map.login  '/login', :controller => 'sessions', :action => 'new'
map.logout '/logout', :controller => 'sessions', :action => 'destroy'

Include restful_authentication in ApplicationController

First remove these lines from the users and sessions controllers:

# Be sure to include AuthenticationSystem in Application Controller instead
  include AuthenticatedSystem

Now include restful_authentication in the application controller:

class ApplicationController < ActionController::Base
  include AuthenticatedSystem

Integrate restful_authentication with your views

First let's create a controller and view by executing the generate script:

script/generate controller home index

Modify index.html.erb as follows:

<h1>Welcome</h1>

<% if logged_in? %>
  <p><strong>You are logged in as <%=h current_user.login %></strong></p>
  <p><%= link_to 'Logout', logout_path %></p>
<% else %>
  <p><strong>You are currently not logged in.</strong></p>
  <p>
    <%= link_to 'Login', login_path %> or
    <%= link_to 'Sign Up', signup_path %>
  </p>
<% end %>

Start Rails and access your application. If needed, add the following to config/routes.rb to make the home controller the default:

map.root :controller => "home"

Login, sign up and logout should work.

How to add OpenID support to your Rails application with the open_id_authentication plugin

Tagged openid, authentication, rails, ruby, plugin, restful_authentication  Languages ruby

These instructions have been tested with Rails 2.0.2 and ruby-openid 2.0.4. The snippet is an adaptation of the instructions in Ryan Bates' screencast on how to integrate OpenID with Rails.

Installing and configuring the restful_authentication plugin

Follow these instructions: How to install and use the restful_authentication Rails plugin.

Installing the ruby-openid gem

gem install ruby-openid

Installing the open_id_authentication Rails plugin

script/plugin source http://svn.techno-weenie.net/projects/plugins/
script/plugin install open_id_authentication

Create the migration files

rake open_id_authentication:db:create

Add the following to the self.up method in 002_add_open_id_authentication_tables.rb:

add_column :users, :identity_url, :string

Configuring the routes

map.open_id_complete 'session', :controller => "sessions", :action => "create", :requirements => { :method => :get }

Protect the identity_url field

Next protect the identity_url field, by adding the following to user.rb, account.rb or your custom user model:

attr_accessible :login, :email, :password, :password_confirmation, :identity_url

Add the following to the self.down method in 002_add_open_id_authentication_tables.rb:

remove_column :users, :identity_url

Integrating Open-id with the login page

Add the following to sessions/new.html.erb:

<label for="openid_url">OpenID URL</label><br />
<%= text_field_tag "openid_url" %>

Make sure you're showing flash messages, otherwise you won't see the error messages:

<html>
  <head></head>
  <body>
    <%= [:notice, :error].collect {|type| content_tag('div', flash[type], :id => type) if flash[type] } %>

    <%= yield %>
  </body>
</html>

Modifying the sessions controller

Copy & paste the following code in app/controllers/sessions_controller.rb:

class SessionsController < ApplicationController
  # Hack to fix: No action responded to show
  def show
    create
  end

  def create
    if using_open_id?
      open_id_authentication(params[:openid_url])
    else
      password_authentication(params[:login], params[:password])
    end
  end

  def destroy
    self.current_user.forget_me if logged_in?
    cookies.delete :auth_token
    reset_session
    flash[:notice] = "You have been logged out."
    redirect_back_or_default('/')
  end

  protected

  def open_id_authentication(openid_url)
    authenticate_with_open_id(openid_url, :required => [:nickname, :email]) do |result, identity_url, registration|
      if result.successful?
        @user = User.find_or_initialize_by_identity_url(identity_url)
        if @user.new_record?
          @user.login = registration['nickname']
          @user.email = registration['email']
          @user.save(false)
        end
        self.current_user = @user
        successful_login
      else
        failed_login result.message
      end
    end
  end

  def password_authentication(login, password)
    self.current_user = User.authenticate(login, password)
    if logged_in?
      successful_login
    else
      failed_login
    end
  end

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

  def successful_login
    if params[:remember_me] == "1"
      self.current_user.remember_me
      cookies[:auth_token] = { :value => self.current_user.remember_token , :expires => self.current_user.remember_token_expires_at }
    end
    redirect_back_or_default('/')
    flash[:notice] = "Logged in successfully"
  end
end

OpenID authentication from behind a proxy

First, set the HTTP_PROXY environment variable to the proxy URL:

export HTTP_PROXY=http://proxy.aktagon.com:8080/

Then add the following to environment.rb:

OpenID::fetcher_use_env_http_proxy