Commit 6540a946 authored by Scott Escue's avatar Scott Escue Committed by Mike Greiling

Preserve URL fragment across sign-in and sign-up redirects

If window.location contains a URL fragment, append the fragment to all sign-in forms, the sign-up form, and all button based providers.
parent 4a6c7661
......@@ -75,6 +75,12 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
private
def omniauth_flow(auth_module, identity_linker: nil)
omniauth_params = request.env['omniauth.params']
if omniauth_params.present? && omniauth_params['redirect_fragment'].present?
store_redirect_fragment(omniauth_params['redirect_fragment'])
end
if current_user
log_audit_event(current_user, with: oauth['provider'])
......@@ -189,4 +195,14 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
request_params = request.env['omniauth.params']
(request_params['remember_me'] == '1') if request_params.present?
end
def store_redirect_fragment(redirect_fragment)
key = stored_location_key_for(:user)
location = session[key]
unless location.to_s.strip.empty?
uri = URI.parse(location)
uri.fragment = redirect_fragment
store_location_for(:user, uri.to_s)
end
end
end
- page_title "Sign in"
%div
- content_for :page_specific_javascripts do
-# haml-lint:disable InlineJavaScript
:javascript
document.addEventListener('DOMContentLoaded', function() {
// Determine if the current URL location contains a fragment identifier (aka hash or anchor ref).
// This should be present if the user was redirected to sign in after attempting to access a
// protected URL that included a fragment identifier.
var fragment = window.location.hash;
if (fragment && fragment !== '') {
// Append the fragment to all signin/signup form actions so it is preserved when
// the user is eventually redirected back to the originally requested URL.
$('div#signin-container form').attr('action', function (index, action) {
return action + fragment;
});
// Append a redirect_fragment query param to all oauth provider links. The redirect_fragment
// query param will be passed to the omniauth callback upon successful authentication
$('div#signin-container a.oauth-login').attr('href', function (index, href) {
const tokens = href.split('?');
let url = tokens[0] + '?redirect_fragment=' + encodeURIComponent(fragment.substr(1));
if (tokens.length > 1) {
url += '&' + tokens[1];
}
return url;
});
}
});
#signin-container
- if form_based_providers.any?
= render 'devise/shared/tabs_ldap'
- else
......
......@@ -45,6 +45,40 @@ describe OmniauthCallbacksController, type: :controller do
end
end
context 'when a redirect fragment is provided' do
let(:provider) { :jwt }
let(:extern_uid) { 'my-uid' }
before do
request.env['omniauth.params'] = { 'redirect_fragment' => 'L101' }
end
context 'when a redirect url is stored' do
it 'redirects with fragment' do
post provider, nil, { user_return_to: '/fake/url' }
expect(response).to redirect_to('/fake/url#L101')
end
end
context 'when a redirect url with a fragment is stored' do
it 'redirects with the new fragment' do
post provider, nil, { user_return_to: '/fake/url#replaceme' }
expect(response).to redirect_to('/fake/url#L101')
end
end
context 'when no redirect url is stored' do
it 'does not redirect with the fragment' do
post provider
expect(response.redirect?).to be true
expect(response.location).not_to include('#L101')
end
end
end
context 'strategies' do
context 'github' do
let(:extern_uid) { 'my-uid' }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment