When I revisit /users/sign_in
after already being signed in, I see the flash You are already signed in.
and the following in my logs..
Filter chain halted as :require_no_authentication rendered or redirected
..and I get redirected to /
. I would like to call a callback and redirect differently depending on some condition.
This is similar in spirit to after_sign_up_path_for
except it's more like "after trying sign in when already signed in".
As Devise support OmniAuth integration by default. In order to do so it creates two extra column provider and uid where provider consist oAuth provider i.e facebook, google, linkedin etc. and uid will consist unique id of the user who logged in using oAuth.
Right now, there's no easy way to accomplish what you want. (Maybe a pull request is in order.)
The problem is that when the user is already authenticated, Devise calls the after_sign_in_path_for
method.
This method is also called when the user logins normally, so even if you override this method, there's no way to distinguish between users who just logged in and those who were already logged in.
The only solution is to extend/override Devise's SessionsController:
class SessionsController < Devise::SessionsController
private
def require_no_authentication
assert_is_devise_resource!
return unless is_navigational_format?
no_input = devise_mapping.no_input_strategies
authenticated = if no_input.present?
args = no_input.dup.push scope: resource_name
warden.authenticate?(*args)
else
warden.authenticated?(resource_name)
end
if authenticated && resource = warden.user(resource_name)
flash[:alert] = I18n.t("devise.failure.already_authenticated")
redirect_to YOUR_PATH_HERE
end
end
end
Since this controller inherits from Devise's, when an action isn't defined in your controller that action will be processed by Devise's controller. So you only have to override that require_no_authentication
method, which is called in a before_filter.
Finally, edit your routes file so this change takes effect:
# routes.rb
devise_for :users, :controllers => { :sessions => 'sessions' }
The easiest way to make sure that the original functionality is preserved is to copy the entire method definition and change parts of it.
def require_no_authentication
assert_is_devise_resource!
return unless is_navigational_format?
no_input = devise_mapping.no_input_strategies
authenticated = if no_input.present?
args = no_input.dup.push scope: resource_name
warden.authenticate?(*args)
else
warden.authenticated?(resource_name)
end
if authenticated && resource = warden.user(resource_name)
# CHANGE THE FOLLOWING LINES AS NEEDED
flash[:alert] = I18n.t("devise.failure.already_authenticated")
redirect_to after_sign_in_path_for(resource)
end
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With