diff --git a/app/forms/two_factor_options_form.rb b/app/forms/two_factor_options_form.rb index 8a3f691394a..84b5efaee27 100644 --- a/app/forms/two_factor_options_form.rb +++ b/app/forms/two_factor_options_form.rb @@ -7,11 +7,7 @@ class TwoFactorOptionsForm validates :selection, inclusion: { in: %w[phone sms voice auth_app piv_cac webauthn webauthn_platform backup_code] } - validates :selection, length: { minimum: 2, message: 'phone' }, if: [ - :multiple_mfa_options_enabled?, - :phone_selected?, - :phone_only_mfa_method?, - ] + validates :selection, length: { minimum: 2, message: 'phone' }, if: :phone_validations? def initialize(user) self.user = user @@ -47,10 +43,6 @@ def update_otp_delivery_preference_for_user UpdateUser.new(user: user, attributes: user_attributes).call end - def multiple_mfa_options_enabled? - IdentityConfig.store.select_multiple_mfa_options - end - def phone_selected? selection.include?('phone') || selection.include?('voice') || selection.include?('sms') end @@ -58,4 +50,15 @@ def phone_selected? def phone_only_mfa_method? MfaContext.new(user).enabled_mfa_methods_count == 0 end + + def phone_alternative_enabled? + count = MfaContext.new(user).enabled_mfa_methods_count + count >= 2 || (count == 1 && MfaContext.new(user).phone_configurations.none?) + end + + def phone_validations? + IdentityConfig.store.select_multiple_mfa_options && + phone_selected? && phone_only_mfa_method? && + !phone_alternative_enabled? + end end diff --git a/spec/forms/two_factor_options_form_spec.rb b/spec/forms/two_factor_options_form_spec.rb index b15ed8d6286..ac0bfa92f47 100644 --- a/spec/forms/two_factor_options_form_spec.rb +++ b/spec/forms/two_factor_options_form_spec.rb @@ -62,5 +62,30 @@ subject.submit(selection: 'auth_app') end end + + context 'when phone is selected as their first authentication method' do + before do + allow(IdentityConfig.store).to receive(:select_multiple_mfa_options).and_return(true) + end + + it 'does not submit the phone when selected as the first single option' do + result = subject.submit(selection: ['phone']) + + expect(result.success?).to eq false + end + end + + context 'when a user wants to select phone as their second authentication method' do + let(:user) { create(:user, :with_authentication_app) } + before do + allow(IdentityConfig.store).to receive(:select_multiple_mfa_options).and_return(true) + end + + it 'submits the form' do + result = subject.submit(selection: ['phone']) + + expect(result.success?).to eq true + end + end end end