diff --git a/lib/clearance/authorization.rb b/lib/clearance/authorization.rb index 4fb574e39..0a36fb3dd 100644 --- a/lib/clearance/authorization.rb +++ b/lib/clearance/authorization.rb @@ -86,10 +86,16 @@ def redirect_back_or(default) def return_to if return_to_url uri = URI.parse(return_to_url) - "#{uri.path}?#{uri.query}".chomp("?") + "##{uri.fragment}".chomp("#") + path = path_without_leading_slashes(uri) + "#{path}?#{uri.query}".chomp("?") + "##{uri.fragment}".chomp("#") end end + # @api private + def path_without_leading_slashes(uri) + uri.path.sub(/\A\/+/, "/") + end + # @api private def return_to_url session[:return_to] diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb index 17575d8c4..f067f9b8b 100644 --- a/spec/controllers/sessions_controller_spec.rb +++ b/spec/controllers/sessions_controller_spec.rb @@ -58,6 +58,19 @@ end context "with good credentials and a session return url" do + it "redirects to the return URL removing leading slashes" do + user = create(:user) + url = "/url_in_the_session?foo=bar#baz" + return_url = "//////#{url}" + request.session[:return_to] = return_url + + post :create, params: { + session: { email: user.email, password: user.password }, + } + + should redirect_to(url) + end + it "redirects to the return URL maintaining query and fragment" do user = create(:user) return_url = "/url_in_the_session?foo=bar#baz"