Rails – Redirect Previous Page After Devise Sign In

By default, Devise will redirect you to the root path after sign in. but sometimes we would like to redirect to the previous page where the anonymous user wanna access. This can be done by the following.

1. Create the app/helpers/sessions_helper.rb

module SessionsHelper

  def deny_access
    store_location
    redirect_to new_user_session_path
  end

  # add back anyone_signed_in? method after Oliver's comment @ 2011-03-12
  def anyone_signed_in?
    !current_user.nil?
  end

  private

    def store_location
      session[:return_to] = request.fullpath
    end

    def clear_stored_location
      session[:return_to] = nil
    end

end

 

2. Include the session helper and customize the Devise after_sign_in_path_for() in app/controllers/application_controller.rb

class ApplicationController < ActionController::Base
  protect_from_forgery
  include SessionsHelper

  # Customize the Devise after_sign_in_path_for() for redirecct to previous page after login
  def after_sign_in_path_for(resource_or_scope)
    case resource_or_scope
    when :user, User
      store_location = session[:return_to]
      clear_stored_location
      (store_location.nil?) ? "/" : store_location.to_s
    else
      super
    end
  end
end

 

3. Request user to login in your controller

...
  def new
    if !anyone_signed_in?
      deny_access
    else
      @service = Service.new
      @title = "Create New Service"
    end
  end
...

 

Done =)

Reference:

Update @ 2011-09-23: If you are using omniauth, the following piece of code may help. Thanks for Allan. =D

def after_sign_in_path_for(resource_or_scope)
   if request.env['omniauth.origin']
      request.env['omniauth.origin']
    end
end

49 thoughts on “Rails – Redirect Previous Page After Devise Sign In”

    1. Hi Oliver,

      The anyone_signed_in? method is a helper method which is defined in a session helper and it is just simply

      def anyone_signed_in?
        !current_user.nil?
      end
      

      The current_user is provided by Devise. Replace the the anyone_signed_in? as follow should work.

      ...
        def new
          if current_user.nil?
            deny_access
          else
            @service = Service.new
            @title = "Create New Service"
          end
        end
      ...
      

      hope this help =)

      Like

  1. After I posted, I tried using the current_user.nil and it worked that way for me! Thanks for the quick reply!

    By the way, can I redirect to the create action? I want the user to enter details of the new record and when they click save, it asks them to login and then proceed to save the record.

    Instead the code below redirects to the tenders index page. To get around it, I save the tender (using the session) in the deny_access method.

    Can I redirect to the create (POST) action and still have access to the tender details that the user entered?

    @tender = Tender.new(params[:tender])
    
     if current_user.nil?
        session[:tender] = @tender
        deny_access
      else
        respond_to do |format|
        if @tender.save
    
            @tenders = Tender.where("user_id = ?", current_user.id)  
            format.html { redirect_to(@tender, :notice => 'Tender was successfully created.') }
            format.xml  { render :xml => @tender, :status => :create
    end
    

    Like

    1. Hi Oliver,

      I haven’t tried this before, but i think it should work.

      probably you need to modify the after_sign_in_path_for(resource_or_scope) and put the tender save logic there instead of placing them in the create method.

      Hope it works. =)

      Kit

      Like

  2. Thats what I did and it works perfect. Just hoping there might be a way of doing it without having to use a session variable!

    Like

    1. then u have to store the form variables somewhere before the user login.

      for example, you could add a column in the tenders table to store its status. then u can save the tender record even the user has not logged in yet. but in that record, just give it a “not complete” status. After the user has logged in, update the status to complete.

      Like

  3. this is interesting…got this to work without sessions at all by using the request.referer

    (request.referer.include? request.fullpath) ? redirect_url = current_user_path : redirect_url = request.referer
    redirect_url

    Like

    1. Thanks ben. but seems your code cannot be shown, could u posted again and wrapped the code with the following tag.

      [sourcecode language=ruby]
      Your code here…
      [/sourcecode]

      Like

    1. O, thx for your information. i didn’t try that before. Need to find some time to update this post.

      Thanks again =D

      Like

    2. i believe this works if the user is forced to login, but if they click the login link without being forced into it, i am setting a session[:return_to] manually so that they are redirected to a certain page instead of the root url.

      Like

      1. @danny , where are you setting this session[:return_to]? I have a similar issue and want to do the same.

        Like

      2. @Igrabes, could u post more detail on your approach?

        @danny, it would be great if you could help.

        Thx =)

        Like

  4. We use Facebook JS to get the access code which then returns back to the omniauth_callback_controller.rb and signs the user in.

    I found that the origin URL is saved in the request. Worked a treat for us.

    in application_controller.rb

    def after_sign_in_path_for(resource_or_scope)
       if request.env['omniauth.origin']
          request.env['omniauth.origin']
        end
    end
    

    Like

  5. hii
    as per your instruction i do but i got message “The page isn’t redirecting properly”
    what i do for fix this error.

    Like

      1. i guess there is a dead loop in the logic. Seems it keeps redirecting to itself so the loop never ends.

        could u post your source code here?

        Like

  6. module SessionsHelper
          def deny_access
          store_location
          redirect_to "/login"
    
        end
    
    	  # add back anyone_signed_in? method after Oliver's comment @ 2011-03-12
          def anyone_signed_in?
            !current_user.nil?
          end
    
    	  private
    
            def store_location
              session[:return_to] = request.fullpath
            end
    
    	    def clear_stored_location
    	      session[:return_to] = nil
    	    end
    end
    

    Like

  7. class ApplicationController < ActionController::Base
      helper :all # include all helpers, all the time
      protect_from_forgery # See ActionController::RequestForgeryProtection for details
      helper_method :authorize
     include SessionsHelper
    
      def after_sign_in_path_for(resource_or_scope)
        case resource_or_scope
        when :user, User
    	      store_location = session[:return_to]
    	      clear_stored_location
          (store_location.nil?) ? "/" : store_location.to_s
        else
          super
    	    end
    	  end
        
    protected
    
    
    def authorize
      unless logged_in?
        flash[:error] = "login required"
        redirect_to "/login"
        false
      end
    end
    
      end
    -----------------------------------------------------------------------------------
    class SessionsController [:create,:new]
       
        layout "defaults"
      def new
        if !anyone_signed_in? 
          
          deny_access
        end
     end
    
      def create
        logout_keeping_session!
        user = User.authenticate(params[:login], params[:password])
        if user
          self.current_user = user
          new_cookie_flag = (params[:remember_me] == "1")
          #handle_remember_cookie! new_cookie_flag
          redirect_to "/home"
          flash[:notice] = "welcome to swagtas blogs"
        else
           note_failed_signin
          @login       = params[:login]
          @remember_me = params[:remember_me]
          
        end
      end
      def welcome
          
      end
      def destroy
        logout_killing_session!
        flash[:notice] = "You have been logged out sucessfully."
        redirect_to('/')
      end
      def home
    
      end
    
      protected
    
      def note_failed_signin
          flash[:error] = "The username or password you entered is incorrect "
        logger.warn "Failed login for '#{params[:login]}' from #{request.remote_ip} at #{Time.now.utc}"
        redirect_to "/login"
      end
    end
    

    Like

  8. new.html with in app/view/session

    
                                      
                    <!-- Uncomment this if you want this functionality
                    
                    
                    -->
    
                    
                    <a href="/signup" rel="nofollow">New User?   </a>
                    
                    <a href="/forget_password" rel="nofollow">Forget password ? </a>
                  
    

    Like

      1. i use this filter before_filter :authorize ,:except=>[:create,:new]
        method create and new used for login

        Like

      2. after review of my code i found that i missplace this

         if !anyone_signed_in?
        
              deny_access
            end
        

        can you help me.. what is the right place for this
        with each and every secure function or any thing else

        Like

      3. In the SessionController, replace the code as follow

        def new
          #if !anyone_signed_in? 
          if !current_user.nil?
            deny_access
          end
        end
        

         

        And remove the anyone_signed_in? method as it is no longer used. Does it help?

        Like

      4. thanks ..its work
        but i m unable to redirect last page(secure page) from where user redirect to login page

        Like

      5. So which page was shown after login? add some debug log in after_sign_in_path_for(resource_or_scope) and see if it was run. also check what is store in session[:return_to].

        Like

      6. sorry, i think i m facing problem becuse i m useing restful_authentication…
        if you have any idea for restful_authentication then let me inform

        thanks a lot for your help

        Like

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.