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:
- Rails Devise only redirects to a fixed path. Need to redirect back where the user came from when authentication was triggered.
- StackOverflow – Devise override redirect after form submit
- How To: Redirect to a specific page on successful sign in
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
This could be really useful if I can get it to work!
Where is the anyone_signed_in method defined?
Hi Oliver,
The anyone_signed_in? method is a helper method which is defined in a session helper and it is just simply
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 =)
Why don’t you use user_signed_in? which is provided by Devise natively
I think it should be ok too. =P
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
ml => @tender, :status => :create
end
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
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!
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.
its really useful for me.. thanks ..
you are welcome =)
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
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]
I believe Devise supports this inherently if you add
before_filter :authenticate_user_account!
to all your relevant controllers.
See the first answer here:
http://stackoverflow.com/questions/5359195/redirecting-after-a-login-to-the-original-task
O, thx for your information. i didn’t try that before. Need to find some time to update this post.
Thanks again =D
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.
ic, thanks for clarifying that. =D
@danny , where are you setting this session[:return_to]? I have a similar issue and want to do the same.
@Igrabes, could u post more detail on your approach?
@danny, it would be great if you could help.
Thx =)
This was super helpful. I did the same thing as Oliver.
Glad to know that it could help. =)
This doesn’t seem to work if you want to send the user to users/password/new to reset their password. It always redirects them to “/”
Maybe you could try the comment made by magnemg
hope it could resolve the problem. =)
Thx, I done it
you are welcome. =D
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 endI have added this to the post. Thanks for the code. =D
after reading this entry, i write a page on devise wiki
https://github.com/plataformatec/devise/wiki/How-To:-Redirect-to-previous-page-on-successful-sign-in
Nice =D
hii
as per your instruction i do but i got message “The page isn’t redirecting properly”
what i do for fix this error.
I find a similar question on the google group.
Firefox has detected that the server is redirecting the request for this address in a way that will never complete.
* This problem can sometimes be caused by disabling or refusing to accept cookies.
Reference: Devise and i18n internationalization and Routes issue
Does it help?
this message shown in google chrome browser This webpage has a redirect loop
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?
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 endclass 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 endnew.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>You will redirect the user to /login when deny_access. so is /login accessible for non-logged in user?
yes /login accessible for non- logged in user.
i use this filter before_filter :authorize ,:except=>[:create,:new]
method create and new used for login
after review of my code i found that i missplace this
if !anyone_signed_in? deny_access endcan you help me.. what is the right place for this
with each and every secure function or any thing else
In the SessionController, replace the code as follow
def new #if !anyone_signed_in? if !current_user.nil? deny_access end endAnd remove the anyone_signed_in? method as it is no longer used. Does it help?
thanks ..its work
but i m unable to redirect last page(secure page) from where user redirect to login page
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].
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
You are welcome. I didn’t help much at all. Wish you could solve the problem. =)
no problem
thanks once again for your continuous helpp
bye
This works like a charm.
I use devise 1.4 in one of my projects. Device actually stores the return path for us in session[resource_return_to], so in most cases, it would be session[:user_return_to]. This can save us a lot of custom code!
http://blog.ashchan.com/archive/2011/08/21/learn-ruby-on-rails/
Good to now that it works for you. =D
Anyone manage to get this working using omniauth.origin?
https://github.com/plataformatec/devise/wiki/How-To:-redirect-to-a-specific-page-on-successful-sign-in
Allan did make it work. you can refer to this comment.