summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Escue <scott.escue@gmail.com>2018-05-22 15:04:19 -0500
committerMike Greiling <mike@pixelcog.com>2019-01-10 00:00:38 -0600
commit6540a9468a8bce3f496423179db1862cfb9f5c8c (patch)
tree28a3c968eeaf8c21377fc80cf0b16c2700b76689
parent4a6c7661edae664a7f6366201d017e24d8f42026 (diff)
downloadgitlab-ce-6540a9468a8bce3f496423179db1862cfb9f5c8c.tar.gz
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.
-rw-r--r--app/controllers/omniauth_callbacks_controller.rb16
-rw-r--r--app/views/devise/sessions/new.html.haml30
-rw-r--r--spec/controllers/omniauth_callbacks_controller_spec.rb34
3 files changed, 79 insertions, 1 deletions
diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb
index 30be50d4595..12f11976439 100644
--- a/app/controllers/omniauth_callbacks_controller.rb
+++ b/app/controllers/omniauth_callbacks_controller.rb
@@ -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
diff --git a/app/views/devise/sessions/new.html.haml b/app/views/devise/sessions/new.html.haml
index 34d4293bd45..3840cbb0b31 100644
--- a/app/views/devise/sessions/new.html.haml
+++ b/app/views/devise/sessions/new.html.haml
@@ -1,6 +1,34 @@
- 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
diff --git a/spec/controllers/omniauth_callbacks_controller_spec.rb b/spec/controllers/omniauth_callbacks_controller_spec.rb
index d377d69457f..21936491ffc 100644
--- a/spec/controllers/omniauth_callbacks_controller_spec.rb
+++ b/spec/controllers/omniauth_callbacks_controller_spec.rb
@@ -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' }