diff --git a/changelogs/unreleased/oauth_bypass_two_factor.yml b/changelogs/unreleased/oauth_bypass_two_factor.yml new file mode 100644 index 00000000000..7261e65a9f3 --- /dev/null +++ b/changelogs/unreleased/oauth_bypass_two_factor.yml @@ -0,0 +1,5 @@ +--- +title: Add option to allow OAuth providers to bypass two factor +merge_request: 31996 +author: Dodocat +type: added diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index 973c2747838..20b1020e025 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -780,6 +780,14 @@ production: &base # (default: []) external_providers: [] + # CAUTION! + # This allows users to login with the specified providers without two factor. Define the allowed providers + # using an array, e.g. ["twitter", 'google_oauth2'], or as true/false to allow all providers or none. + # This option should only be configured for providers which already have two factor. + # This configration dose not apply to SAML. + # (default: false) + allow_bypass_two_factor: ["twitter", 'google_oauth2'] + ## Auth providers # Uncomment the following lines and fill in the data of the auth provider you want to use # If your favorite auth provider is not listed you can use others: diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb index fdc6b0a05ab..81433b620bc 100644 --- a/config/initializers/1_settings.rb +++ b/config/initializers/1_settings.rb @@ -84,6 +84,7 @@ Settings['omniauth'] ||= Settingslogic.new({}) Settings.omniauth['enabled'] = true if Settings.omniauth['enabled'].nil? Settings.omniauth['auto_sign_in_with_provider'] = false if Settings.omniauth['auto_sign_in_with_provider'].nil? Settings.omniauth['allow_single_sign_on'] = false if Settings.omniauth['allow_single_sign_on'].nil? +Settings.omniauth['allow_bypass_two_factor'] = false if Settings.omniauth['allow_bypass_two_factor'].nil? Settings.omniauth['external_providers'] = [] if Settings.omniauth['external_providers'].nil? Settings.omniauth['block_auto_created_users'] = true if Settings.omniauth['block_auto_created_users'].nil? Settings.omniauth['auto_link_ldap_user'] = false if Settings.omniauth['auto_link_ldap_user'].nil? diff --git a/doc/integration/omniauth.md b/doc/integration/omniauth.md index 7a92ed994c7..0fc5a25ae33 100644 --- a/doc/integration/omniauth.md +++ b/doc/integration/omniauth.md @@ -277,3 +277,23 @@ omniauth: sync_profile_from_provider: ['twitter', 'google_oauth2'] sync_profile_attributes: ['email', 'location'] ``` +## Bypassing two factor authentication + +Starting with GitLab 12.3, this allows users to login with the specified +providers without two factor authentication. + +Define the allowed providers using an array, e.g. `["twitter", 'google_oauth2']`, or as +`true`/`false` to allow all providers or none. This option should only be configured +for providers which already have two factor authentication (default: false). +This configration dose not apply to SAML. + +```ruby +gitlab_rails['omniauth_allow_bypass_two_factor'] = ['twitter', 'google_oauth2'] +``` + +**For installations from source** + +```yaml +omniauth: + allow_bypass_two_factor: ['twitter', 'google_oauth2'] +``` diff --git a/lib/gitlab/auth/o_auth/user.rb b/lib/gitlab/auth/o_auth/user.rb index 09d1d79fefc..f121dce4cbb 100644 --- a/lib/gitlab/auth/o_auth/user.rb +++ b/lib/gitlab/auth/o_auth/user.rb @@ -77,7 +77,12 @@ module Gitlab end def bypass_two_factor? - false + providers = Gitlab.config.omniauth.allow_bypass_two_factor + if providers.is_a?(Array) + providers.include?(auth_hash.provider) + else + providers + end end protected diff --git a/spec/features/oauth_login_spec.rb b/spec/features/oauth_login_spec.rb index a47eaa9bda7..c6e69fa3fb0 100644 --- a/spec/features/oauth_login_spec.rb +++ b/spec/features/oauth_login_spec.rb @@ -55,6 +55,18 @@ describe 'OAuth Login', :js, :allow_forgery_protection do expect(current_path).to eq root_path end + + it 'when bypass-two-factor is enabled' do + allow(Gitlab.config.omniauth).to receive_messages(allow_bypass_two_factor: true) + login_via(provider.to_s, user, uid, remember_me: false) + expect(current_path).to eq root_path + end + + it 'when bypass-two-factor is disabled' do + allow(Gitlab.config.omniauth).to receive_messages(allow_bypass_two_factor: false) + login_with_provider(provider, enter_two_factor: true) + expect(current_path).to eq root_path + end end context 'when "remember me" is checked' do diff --git a/spec/lib/gitlab/auth/o_auth/user_spec.rb b/spec/lib/gitlab/auth/o_auth/user_spec.rb index a9b15c411dc..1e3da4f7c2d 100644 --- a/spec/lib/gitlab/auth/o_auth/user_spec.rb +++ b/spec/lib/gitlab/auth/o_auth/user_spec.rb @@ -787,11 +787,25 @@ describe Gitlab::Auth::OAuth::User do end end - describe '#bypass_two_factor?' do - subject { oauth_user.bypass_two_factor? } + describe "#bypass_two_factor?" do + it "when with allow_bypass_two_factor disabled (Default)" do + stub_omniauth_config(allow_bypass_two_factor: false) + expect(oauth_user.bypass_two_factor?).to be_falsey + end - it 'returns always false' do - is_expected.to be_falsey + it "when with allow_bypass_two_factor enabled" do + stub_omniauth_config(allow_bypass_two_factor: true) + expect(oauth_user.bypass_two_factor?).to be_truthy + end + + it "when provider in allow_bypass_two_factor array" do + stub_omniauth_config(allow_bypass_two_factor: [provider]) + expect(oauth_user.bypass_two_factor?).to be_truthy + end + + it "when provider not in allow_bypass_two_factor array" do + stub_omniauth_config(allow_bypass_two_factor: ["foo"]) + expect(oauth_user.bypass_two_factor?).to be_falsey end end end