Skip to content

Commit 23ca169

Browse files
committed
Redirect to space on subdomain following successful omniauth auth
1 parent d1b63b0 commit 23ca169

File tree

5 files changed

+95
-4
lines changed

5 files changed

+95
-4
lines changed

app/controllers/callbacks_controller.rb

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ class CallbacksController < Devise::OmniauthCallbacksController
1111

1212
def handle_callback(provider, config)
1313
@user = User.from_omniauth(request.env["omniauth.auth"])
14+
if request.env['omniauth.params'] && request.env['omniauth.params']['space_id']
15+
space = Space.find_by_id(request.env['omniauth.params']['space_id'])
16+
end
1417

1518
if @user.new_record?
1619
# new user
@@ -27,13 +30,28 @@ def handle_callback(provider, config)
2730

2831
sign_in @user
2932
flash[:notice] = "#{I18n.t('devise.registrations.signed_up')} Please ensure your profile is correct."
30-
redirect_to edit_user_path(@user)
33+
redirect_to_space(edit_user_path(@user), space)
3134
rescue Exception => e
3235
flash[:notice] = "Login failed: #{e.message.to_s}"
33-
redirect_to new_user_session_path
36+
redirect_to_space(new_user_session_path, space)
3437
end
3538
else
36-
sign_in_and_redirect @user
39+
scope = Devise::Mapping.find_scope!(@user)
40+
sign_in(scope, resource, {})
41+
redirect_to_space(after_sign_in_path_for(@user), space)
42+
end
43+
end
44+
45+
private
46+
47+
def redirect_to_space(path, space)
48+
if space && space.is_subdomain?(request.domain)
49+
port_part = ''
50+
port_part = ":#{request.port}" if (request.protocol == "http://" && request.port != 80) ||
51+
(request.protocol == "https://" && request.port != 443)
52+
redirect_to URI.join("#{request.protocol}#{space.host}#{port_part}", path).to_s, allow_other_host: true
53+
else
54+
redirect_to path
3755
end
3856
end
3957

app/helpers/application_helper.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -700,11 +700,12 @@ def theme_path
700700
end
701701

702702
def omniauth_login_link(provider, config)
703+
params = Space.current_space&.default? ? {} : { space_id: Space.current_space.id }
703704
link_to(
704705
t('authentication.omniauth.log_in_with',
705706
provider: config.options[:label] ||
706707
t("authentication.omniauth.providers.#{provider}", default: provider.to_s.titleize)),
707-
omniauth_authorize_path('user', provider),
708+
omniauth_authorize_path('user', provider, **params),
708709
method: :post
709710
)
710711
end

app/models/space.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ def enabled_features
6565
(FEATURES - disabled_features)
6666
end
6767

68+
def is_subdomain?(domain)
69+
(host == domain || host.ends_with?(".#{domain}"))
70+
end
71+
6872
private
6973

7074
def disabled_features_valid?

test/integration/omniauth_test.rb

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,4 +399,64 @@ class OmniauthTest < ActionDispatch::IntegrationTest
399399
assert_response :not_found
400400
end
401401

402+
test 'authentication redirects users back to origin space on subdomain' do
403+
space = spaces(:astro)
404+
space.update!(host: 'space.example.com')
405+
406+
OmniAuth.config.mock_auth[:oidc] = OmniAuth::AuthHash.new(
407+
{
408+
provider: 'oidc',
409+
uid: '0123456789abcdcef',
410+
info: {
411+
email: 'aai@example.com',
412+
nickname: 'aaf_user',
413+
first_name: 'AAF',
414+
last_name: 'User'
415+
}
416+
})
417+
418+
post user_oidc_omniauth_authorize_url(space_id: space.id)
419+
follow_redirect! # OmniAuth redirect
420+
assert_equal "http://space.example.com/users/aaf_user/edit", response.headers['Location']
421+
end
422+
423+
test 'authentication does not redirect user to entirely different domain' do
424+
space = spaces(:astro)
425+
space.update!(host: 'my-cool-space-host.com')
426+
427+
OmniAuth.config.mock_auth[:oidc] = OmniAuth::AuthHash.new(
428+
{
429+
provider: 'oidc',
430+
uid: '0123456789abcdcef',
431+
info: {
432+
email: 'aai@example.com',
433+
nickname: 'aaf_user',
434+
first_name: 'AAF',
435+
last_name: 'User'
436+
}
437+
})
438+
439+
post user_oidc_omniauth_authorize_url(space_id: space.id)
440+
follow_redirect! # OmniAuth redirect
441+
assert_equal "http://www.example.com/users/aaf_user/edit", response.headers['Location']
442+
end
443+
444+
test 'invalid space is ignored when redirecting' do
445+
OmniAuth.config.mock_auth[:oidc] = OmniAuth::AuthHash.new(
446+
{
447+
provider: 'oidc',
448+
uid: '0123456789abcdcef',
449+
info: {
450+
email: 'aai@example.com',
451+
nickname: 'aaf_user',
452+
first_name: 'AAF',
453+
last_name: 'User'
454+
}
455+
})
456+
457+
post user_oidc_omniauth_authorize_url(space_id: 'ufhgfsdkhgskdjfhsdkjfhsdkjfhsd')
458+
follow_redirect! # OmniAuth redirect
459+
assert_equal "http://www.example.com/users/aaf_user/edit", response.headers['Location']
460+
end
461+
402462
end

test/models/space_test.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,4 +128,12 @@ class SpaceTest < ActiveSupport::TestCase
128128
@space.enabled_features = Space::FEATURES
129129
assert_equal [], @space.disabled_features
130130
end
131+
132+
test 'check subdomain of' do
133+
assert @space.is_subdomain?('mytess.training')
134+
refute @space.is_subdomain?('amytess.training')
135+
refute @space.is_subdomain?('mytess.com')
136+
refute @space.is_subdomain?('mytess.training.com')
137+
refute @space.is_subdomain?('space.mytess.training')
138+
end
131139
end

0 commit comments

Comments
 (0)