03 January 2010

User Authentication in Rails : AuthLogic

Working on any web application, there is always a need to have user authentication system running in the application. Ruby on Rails is blessed to have a such an active community which always comes up with solutions to rails of any kind. For user authentication there is an awesome plugin called AuthLogic. I have used this plugin in an application I am currently associated with and it works like a charm.

In this post you can find step by step instruction on getting this plugin up and running in your application.

Installing AuthLogic

AuthLogic can either be installed as a plugin or as a gem. I would rather go with installing a gem. So from the command line:
gem install authlogic
After installing the gem, we will be creating a very simple rails application just to test the user authentication functionality via authlogic gem.

So from command line create a new application named user_authentication_demo
C:\>rails user_authentication_demo -d mysql
after the application is created, lets just go ahead and create a dummy controller dummy method in the controller and a dummy view. This is just to have a page up and running where we will be displaying the working of user authentication functionality.

So create a controller by:
C:\user_authentication_demo>ruby script/generate controller home index
You can add some dummy text in your app/views/index.html.erb file just for fun. Working on rails, you got enough time for fun stuffs !
(Make sure you have <%= flash[:notice] %> in there to get the flash messages)

Next open up the config/database.yml find athen replace the entire content here with the following code
development:
      host: localhost
      adapter: mysql
      database: user_authentication_demo_development
      port: 3307
      username: root
      password:

test:
      host: localhost
      adapter: mysql

production:
      host: localhost
      adapter: mysql

All I have done is removed unwanted junk of codes from there to keep it straight and simple.

Now if we run the server and go to http://localhost:3000/blog, we will be taken to the dummy page as shown below:



We will be adding the user authentication to the above page. In this page we will be showing "Register","Login" links if the user is not logged in and "Edit Profile","Logout" links if the user is logged in.

Next we need to create Model and Controller for Users. First we will be generating our User Model
C:\user_authentication_demo>ruby script/generate model user
After all the associated files are created, we will edit the migration file at db/migrate/20100103124423_create_users.rb and ad the following codes in it.
class CreateUsers < ActiveRecord::Migration  
  def self.up  
    create_table :users do |t|  
      t.string :username  
      t.string :email  
      t.string :crypted_password  
      t.string :password_salt  
      t.string :persistence_token  
      t.timestamps  
    end  
  end   

  def self.down  
    drop_table :users  
  end  
end
AuthLogic can pretty much handle fields called email, crypted_password, password_salt and persistence_token and hence we need not bother much about them So let's go ahead and run rake to create the database tables
C:\user_authentication_demo>rake db:migrate
Next we will have to edit the app/models/user.rb file and add the following codes in it
class User < ActiveRecord::Base
  acts_as_authentic 
end
This is to add the Authlogic to the class, without which it will be just a standard model class. Our next task is to create users controller. Also we require new and edit views, and hence we will make sure to create them through generators by the following command
C:\user_authentication_demo>ruby script/generate controller users new edit
Next we need to modify config/routes.rb file a bit and add the following line of code
map.resources :users  
Now inorder to display the link for "Register" , in all the pages of your application add the following lines in your app/views/layouts/application.html.erb file(If you dont have application.html.erb file, then create it)
<%= link_to "Register", new_user_path %>
<%= yield %>
Next add the following bunch of code in app/controllers/user_controller.rb
class UsersController < ApplicationController

 def new  
  @user = User.new  
 end  

 def create  
  @user = User.new(params[:user])  
  if @user.save  
   flash[:notice] = "Registration successful."  
   redirect_to :controller=>"blog"  
  else  
   render :action => 'new'  
  end  
 end 

 def edit
 end

end
We will be putting the code for registration in a partial as we will require it for registration as well as editing. So create a patial file in app/views/users/_user.html.erb and add the following codes in it.
<% form_for @user do |form| %>  
 <%= form.error_messages %>  
 

  1. <%= form.label :username, "Username" %> <%= form.text_field :username %>
  2. <%= form.label :email, "Email" %> <%= form.text_field :email %>
  3. <%= form.label :password, "Password" %> <%= form.password_field :password %>
  4. <%= form.label :password_confirmation, "Password confirmation" %> <%= form.password_field :password_confirmation %>
  5. <%= form.submit "Submit" %>
<% end %>
And then add the following code in the app/views/users/new.html.erb to call the partial for registration purpose
<%= render @user %>  
Now if we check http://localhost:3000/blog we will see the "register" link and if we click on the link, we will be taken to the registration form. If we click on the register button without entering any details, we will get the validation errors and if we enter valid data and then register we will be redirected to blog page. So far so good. next we will add a "Login" link next to "registration" link to let our users to login to the application. For this we have to create UserSession model to get the current status of our users. From the command line,
C:\user_authentication_demo>ruby script/generate session user_session
This generator will create UserSession model and this model will be just have an empty class. Next we generate controller for the UserSession
C:\user_authentication_demo>ruby script/generate controller UserSessions
And add the following codes within the UserSessions Controller
class UserSessionsController < ApplicationController

 def new  
   @user_session = UserSession.new  
 end  
 
 def create  
   @user_session = UserSession.new(params[:user_session])  
   if @user_session.save  
     flash[:notice] = "Successfully logged in."  
    redirect_to :controller=>"blog"  
   else  
     render :action => 'new'  
   end  
 end 
 
 def destroy  
   @user_session = UserSession.find  
   @user_session.destroy  
   flash[:notice] = "Successfully logged out."  
   redirect_to :controller=>"blog"   
 end 

end
Next create a view file in app/views/user_sessions/new.html.erb and add the following codes
<% form_for @user_session do |form| %>  
 <%= form.error_messages %>  
 

  1. <%= form.label :username, "Username" %> <%= form.text_field :username %>
  2. <%= form.label :password, "Password" %> <%= form.password_field :password %>
  3. <%= form.submit "Submit" %>
<% end %>
We will have to edit the config/routes.rb a bit to add the following codes.
map.login 'login', :controller => 'user_sessions', :action => 'new'  
  map.logout 'logout', :controller => 'user_sessions', :action => 'destroy'  
  map.resources :user_sessions
We can also modify our application.rhtml file to add the link for login
<%= link_to "Register", new_user_path %> | <%= link_to "Log in", login_path %>
Now if we check our blog page along with "Register" link we also ha "Login" link and if we click on "Login", we will be taken to a Login page with fields for username and password. Upon valid username and password entry, we will be taken to blog page with a flash message. On invalid login details, we will end up with validation errors. Our next aim is to write code for logging out and display "Edit Profile" and "Logout" Links for the logged in users. So let us modify the application.rhtml and have the following codes in there:
<% if current_user %> <%= link_to "Edit profile", edit_user_path(:current) %> <%= link_to "Logout", logout_path %> <% else %> <%= link_to "Register", new_user_path %> <%= link_to "Log in", login_path %> <% end %>
<%= yield %>
And also add the following code in the app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
    helper_method :current_user  
      
    private  
    def current_user_session  
      return @current_user_session if defined?(@current_user_session)  
      @current_user_session = UserSession.find  
    end  
      
    def current_user  
     @current_user = current_user_session && current_user_session.record  
   end  
end

To make the "Edit profile" working modify the user_session controller to
class UsersController < ApplicationController

 def new  
  @user = User.new  
 end  

 def create  
  @user = User.new(params[:user])  
  if @user.save  
   flash[:notice] = "Registration successful."  
   redirect_to :controller=>"blog"
  else  
   render :action => 'new'  
  end  
 end 

    def edit  
      @user = current_user  
    end  
      
    def update  
      @user = current_user  
      if @user.update_attributes(params[:user])  
        flash[:notice] = "Successfully updated profile."  
        redirect_to :controller=>"blog"  
     else  
       render :action => 'edit'  
     end  
   end  

end

And then we have to call the form partial by adding the following code within /app/views/users/edit.html.erb
<%= render @user %>


Thats it. We are set to go with our application with this wonderfull gem/plugin for the user authentication functionality.

6 comments:

  1. How difficult do you think will be a Jquery based sliding form using the concepts you have discussed here..

    ReplyDelete
  2. I'm using authlogic in a project I'm doing right now. I tried out RESTful authentication earlier, and even though it's much easier to set up, it produces too much code. I prefer having more control over how the authentication system works rather than leaving it all to the generated code.

    Btw, are there any other authentication plugins I should try out? I've only tried out authlogic and RESTful authentication so far and have been looking for something else I could try out. Any suggestions?

    ReplyDelete
  3. This doesn't work.
    And has lots of errors.
    It never mentions something about creating anything called "blog" and suddenly it start using "blog" everywhere.
    Writing "acts_as_authentic" does nothing. It makes the server send an error (undefined local variable or method `acts_as_authentic' for User).
    I installed the authlogic gem.
    Maybe I'm doing something wrong. Any help?

    ReplyDelete
  4. your usersession class must inherite from Authlogic::Session::Base
    to get the code work use:
    class UserSession < Authlogic::Session::Base
    def to_key
    new_record? ? nil : [ self.send(self.class.primary_key) ]
    end

    def persisted?
    false
    end
    end

    ReplyDelete
  5. for a proper tutorial use the followig link...
    personally I found it he best one as far as Rails 3 is concerned..

    http://www.logansbailey.com/2010/10/06/how-to-setup-authlogic-in-rails-3/

    ReplyDelete
  6. There are few errors in this link. Couldnt follow it completely

    ReplyDelete

Share your thoughts, Lets have a discussion :)