summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/controllers/omniauth_callbacks_controller.rb6
-rw-r--r--spec/features/login_spec.rb43
-rw-r--r--spec/support/login_helpers.rb34
-rw-r--r--spec/support/omni_auth.rb1
4 files changed, 78 insertions, 6 deletions
diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb
index f35d631df0c..f54c79c2e37 100644
--- a/app/controllers/omniauth_callbacks_controller.rb
+++ b/app/controllers/omniauth_callbacks_controller.rb
@@ -107,7 +107,11 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
# Only allow properly saved users to login.
if @user.persisted? && @user.valid?
log_audit_event(@user, with: oauth['provider'])
- sign_in_and_redirect(@user)
+ if @user.two_factor_enabled?
+ prompt_for_two_factor(@user)
+ else
+ sign_in_and_redirect(@user)
+ end
else
error_message = @user.errors.full_messages.to_sentence
diff --git a/spec/features/login_spec.rb b/spec/features/login_spec.rb
index 72b5ff231f7..58753ff21f6 100644
--- a/spec/features/login_spec.rb
+++ b/spec/features/login_spec.rb
@@ -28,6 +28,11 @@ feature 'Login', feature: true do
end
describe 'with two-factor authentication' do
+ def enter_code(code)
+ fill_in 'Two-Factor Authentication code', with: code
+ click_button 'Verify code'
+ end
+
context 'with valid username/password' do
let(:user) { create(:user, :two_factor) }
@@ -36,11 +41,6 @@ feature 'Login', feature: true do
expect(page).to have_content('Two-Factor Authentication')
end
- def enter_code(code)
- fill_in 'Two-Factor Authentication code', with: code
- click_button 'Verify code'
- end
-
it 'does not show a "You are already signed in." error message' do
enter_code(user.current_otp)
expect(page).not_to have_content('You are already signed in.')
@@ -108,6 +108,39 @@ feature 'Login', feature: true do
end
end
end
+
+ context 'logging in via OAuth' do
+ def saml_config
+ OpenStruct.new(name: 'saml', label: 'saml', args: {
+ assertion_consumer_service_url: 'https://localhost:3443/users/auth/saml/callback',
+ idp_cert_fingerprint: '26:43:2C:47:AF:F0:6B:D0:07:9C:AD:A3:74:FE:5D:94:5F:4E:9E:52',
+ idp_sso_target_url: 'https://idp.example.com/sso/saml',
+ issuer: 'https://localhost:3443/',
+ name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient'
+ })
+ end
+
+ def stub_omniauth_config(messages)
+ Rails.application.env_config['devise.mapping'] = Devise.mappings[:user]
+ Rails.application.routes.disable_clear_and_finalize = true
+ Rails.application.routes.draw do
+ post '/users/auth/saml' => 'omniauth_callbacks#saml'
+ end
+ allow(Gitlab::OAuth::Provider).to receive_messages(providers: [:saml], config_for: saml_config)
+ allow(Gitlab.config.omniauth).to receive_messages(messages)
+ allow_any_instance_of(Object).to receive(:user_omniauth_authorize_path).with('saml').and_return('/users/auth/saml')
+ end
+
+ it 'should show 2FA prompt after OAuth login' do
+ stub_omniauth_config(enabled: true, auto_link_saml_user: true, allow_single_sign_on: ['saml'], providers: [saml_config])
+ user = create(:omniauth_user, :two_factor, extern_uid: 'my-uid', provider: 'saml')
+ login_via('saml', user, 'my-uid')
+
+ expect(page).to have_content('Two-Factor Authentication')
+ enter_code(user.current_otp)
+ expect(current_path).to eq root_path
+ end
+ end
end
describe 'without two-factor authentication' do
diff --git a/spec/support/login_helpers.rb b/spec/support/login_helpers.rb
index ffdf2bb0a8a..e5f76afbfc0 100644
--- a/spec/support/login_helpers.rb
+++ b/spec/support/login_helpers.rb
@@ -37,6 +37,40 @@ module LoginHelpers
Thread.current[:current_user] = user
end
+ def login_via(provider, user, uid)
+ mock_auth_hash(provider, uid, user.email)
+ visit new_user_session_path
+ click_link provider
+ end
+
+ def mock_auth_hash(provider, uid, email)
+ # The mock_auth configuration allows you to set per-provider (or default)
+ # authentication hashes to return during integration testing.
+ OmniAuth.config.mock_auth[provider.to_sym] = OmniAuth::AuthHash.new({
+ provider: provider,
+ uid: uid,
+ info: {
+ name: 'mockuser',
+ email: email,
+ image: 'mock_user_thumbnail_url'
+ },
+ credentials: {
+ token: 'mock_token',
+ secret: 'mock_secret'
+ },
+ extra: {
+ raw_info: {
+ info: {
+ name: 'mockuser',
+ email: email,
+ image: 'mock_user_thumbnail_url'
+ }
+ }
+ }
+ })
+ Rails.application.env_config['omniauth.auth'] = OmniAuth.config.mock_auth[:saml]
+ end
+
# Requires Javascript driver.
def logout
find(".header-user-dropdown-toggle").click
diff --git a/spec/support/omni_auth.rb b/spec/support/omni_auth.rb
new file mode 100644
index 00000000000..0b1af4052ff
--- /dev/null
+++ b/spec/support/omni_auth.rb
@@ -0,0 +1 @@
+OmniAuth.config.test_mode = true