devise
devise copied to clipboard
Rails 7: allow redirections to other/external hosts after logout.
Context
When using different authentication strategies, devise_saml_autheticatable in my case, it's common to redirect the user to an external host after logout.
Rails 7 requires to explicitly pass allow_other_host: true
to redirect_to
to allow such redirections. Otherwise, an ugly exception is raised.
- Devise
4.8.1
- Rails
7.0.1
Expected behaviour.
When using devise with Rails 7 and setting the after_sign_out_path_for
to an external host, the user is sucessfully redirected.
Current behaviour.
When using devise with Rails 7 and setting the after_sign_out_path_for
to an external host, a ActionController::Redirecting::UnsafeRedirectError
is raised.
There are other places than logout that redirect_to
would need allow_other_host: true
.
For instance, if I'm on me.site.com
and load site.com/sign_in
, I'll get redirected back to me.site.com
which would raise the exception here...
https://github.com/heartcombo/devise/blob/v4.8.1/app/controllers/devise_controller.rb#L116
I don't know how many instances like this there are
There are other places than logout that
redirect_to
would needallow_other_host: true
.
Yes indeed. For instance we need to be able to set it for the registrations_controller: https://github.com/heartcombo/devise/blob/v4.8.1/app/controllers/devise/registrations_controller.rb#L25-L29
Any chance this will be looked into soon? The same issue happens if after_sign_in_path_for is overridden to return an external host. For now I'm making do by overriding Devise::SessionsController#create.
I'm also having this issue because I want to redirect to an external Stripe checkout page after a user signs up. For now I am overriding the respond_with
method:
def respond_with(resource, location: nil)
if !resource.persisted? || resource.active_for_authentication?
super
else
co_session = Stripe::Checkout::Session.create(...)
redirect_to co_session.url, allow_other_host: true
end
end
Seems like the best way to approach this is add a alow_directs_to_other_hosts
configuration under Devise.configure
, and then use that everywhere redirect_to
is currently used.
Should be relatively straightforward I think
+1 on improvements here, my login broke after a Rails 7 upgrade because I am routing users to a per-user custom external URLs in after_sign_in_path_for
+1 to improvements here, for now we will have to set this new config to false to have our app to still work with devise.
+1 Haven't found another way than setting action_controller.raise_on_open_redirects = false
, more than a year later
I just ran in to this problem in project and fixed it across the entirety of devise with
class DeviseController
# monkey patching devise so it can handle the new default behaviour in rails 7
# redirects
original_redirect_to = instance_method(:redirect_to)
define_method(:redirect_to) do |options, response_options = {}|
if options.is_a?(Hash)
options[:allow_other_host] = true unless options.key?(:allow_other_host)
elsif response_options.is_a?(Hash)
response_options[:allow_other_host] = true unless response_options.key?(:allow_other_host)
end
original_redirect_to
.bind_call(self, options, response_options)
end
end
But please can this be fixed properly?