diff --git a/app/policies/service_provider_mfa_policy.rb b/app/policies/service_provider_mfa_policy.rb index 156bc9882a5..fdf62e5a694 100644 --- a/app/policies/service_provider_mfa_policy.rb +++ b/app/policies/service_provider_mfa_policy.rb @@ -50,12 +50,6 @@ def piv_cac_required? piv_cac_requested? end - def allow_user_to_switch_method? - return false if piv_cac_required? - return true unless phishing_resistant_required? - piv_cac_enabled? && webauthn_enabled? - end - def multiple_factors_enabled? mfa_context.enabled_mfa_methods_count > 1 end diff --git a/app/presenters/two_factor_auth_code/generic_delivery_presenter.rb b/app/presenters/two_factor_auth_code/generic_delivery_presenter.rb index 5e353266e90..5bb04e1b33c 100644 --- a/app/presenters/two_factor_auth_code/generic_delivery_presenter.rb +++ b/app/presenters/two_factor_auth_code/generic_delivery_presenter.rb @@ -4,7 +4,7 @@ class GenericDeliveryPresenter include ActionView::Helpers::TranslationHelper include Rails.application.routes.url_helpers - attr_reader :code_value, :reauthn + attr_reader :code_value, :reauthn, :service_provider def initialize(data:, view:, service_provider:, remember_device_default: true) data.each do |key, value| @@ -19,26 +19,18 @@ def header raise NotImplementedError end - def link_text - t('two_factor_authentication.login_options_link_text') - end - - def link_path - login_two_factor_options_path - end - def redirect_location_step; end def troubleshooting_options [ choose_another_method_troubleshooting_option, learn_more_about_authentication_options_troubleshooting_option, - ].select(&:present?) + ] end def choose_another_method_troubleshooting_option - return if link_path.blank? - BlockLinkComponent.new(url: link_path).with_content(link_text) + BlockLinkComponent.new(url: login_two_factor_options_path). + with_content(t('two_factor_authentication.login_options_link_text')) end def learn_more_about_authentication_options_troubleshooting_option diff --git a/app/presenters/two_factor_auth_code/piv_cac_authentication_presenter.rb b/app/presenters/two_factor_auth_code/piv_cac_authentication_presenter.rb index d1d13877e87..4e77b7851ad 100644 --- a/app/presenters/two_factor_auth_code/piv_cac_authentication_presenter.rb +++ b/app/presenters/two_factor_auth_code/piv_cac_authentication_presenter.rb @@ -6,55 +6,10 @@ def header t('two_factor_authentication.piv_cac_header_text') end - def piv_cac_help - if service_provider_mfa_policy.phishing_resistant_required? && - service_provider_mfa_policy.allow_user_to_switch_method? - t('instructions.mfa.piv_cac.confirm_piv_cac_or_aal3') - elsif service_provider_mfa_policy.phishing_resistant_required? || - service_provider_mfa_policy.piv_cac_required? - t('instructions.mfa.piv_cac.confirm_piv_cac_only') - else - t('instructions.mfa.piv_cac.confirm_piv_cac') - end - end - def piv_cac_capture_text t('forms.piv_cac_mfa.submit') end - def link_text - if service_provider_mfa_policy.phishing_resistant_required? - if service_provider_mfa_policy.allow_user_to_switch_method? - t('two_factor_authentication.piv_cac_webauthn_available') - else - '' - end - else - super - end - end - - def link_path - if service_provider_mfa_policy.phishing_resistant_required? - if service_provider_mfa_policy.allow_user_to_switch_method? - login_two_factor_webauthn_url - else - '' - end - else - super - end - end - - def troubleshooting_options - options = [] - if service_provider_mfa_policy.allow_user_to_switch_method? - options << choose_another_method_troubleshooting_option - end - options << learn_more_about_authentication_options_troubleshooting_option - options - end - def cancel_link if reauthn account_path diff --git a/app/presenters/two_factor_auth_code/webauthn_authentication_presenter.rb b/app/presenters/two_factor_auth_code/webauthn_authentication_presenter.rb index 8778ad578a9..392f2a06d91 100644 --- a/app/presenters/two_factor_auth_code/webauthn_authentication_presenter.rb +++ b/app/presenters/two_factor_auth_code/webauthn_authentication_presenter.rb @@ -17,12 +17,7 @@ def initialize(data:, view:, service_provider:, remember_device_default: true, end def webauthn_help - if service_provider_mfa_policy.phishing_resistant_required? && - service_provider_mfa_policy.allow_user_to_switch_method? - t('instructions.mfa.webauthn.confirm_webauthn_or_aal3') - elsif service_provider_mfa_policy.phishing_resistant_required? - t('instructions.mfa.webauthn.confirm_webauthn_only') - elsif platform_authenticator? + if platform_authenticator? t('instructions.mfa.webauthn.confirm_webauthn_platform', app_name: APP_NAME) else t('instructions.mfa.webauthn.confirm_webauthn') @@ -45,32 +40,8 @@ def header end end - def link_text - if service_provider_mfa_policy.phishing_resistant_required? - if service_provider_mfa_policy.allow_user_to_switch_method? - t('two_factor_authentication.webauthn_piv_available') - else - '' - end - else - super - end - end - - def link_path - if service_provider_mfa_policy.phishing_resistant_required? - if service_provider_mfa_policy.allow_user_to_switch_method? - login_two_factor_piv_cac_url - else - '' - end - else - super - end - end - def troubleshooting_options - options = [choose_another_method_troubleshooting_option].select(&:present?) + options = [choose_another_method_troubleshooting_option] if platform_authenticator? options << BlockLinkComponent.new( url: help_center_redirect_path( diff --git a/app/presenters/two_factor_login_options_presenter.rb b/app/presenters/two_factor_login_options_presenter.rb index fca7e808f19..355e06fc5ad 100644 --- a/app/presenters/two_factor_login_options_presenter.rb +++ b/app/presenters/two_factor_login_options_presenter.rb @@ -1,7 +1,10 @@ class TwoFactorLoginOptionsPresenter < TwoFactorAuthCode::GenericDeliveryPresenter include ActionView::Helpers::TranslationHelper - attr_reader :user + attr_reader :user, :phishing_resistant_required, :piv_cac_required + + alias_method :phishing_resistant_required?, :phishing_resistant_required + alias_method :piv_cac_required?, :piv_cac_required def initialize( user:, @@ -31,6 +34,14 @@ def info t('two_factor_authentication.login_intro') end + def restricted_options_warning_text + if piv_cac_required? + t('two_factor_authentication.aal2_request.piv_cac_only_html', sp_name:) + elsif phishing_resistant_required? + t('two_factor_authentication.aal2_request.phishing_resistant_html', sp_name:) + end + end + def options mfa = MfaContext.new(user) @@ -107,4 +118,12 @@ def account_reset_token def account_reset_token_valid? user&.account_reset_request&.granted_token_valid? end + + def sp_name + if service_provider + service_provider.friendly_name + else + APP_NAME + end + end end diff --git a/app/views/two_factor_authentication/options/index.html.erb b/app/views/two_factor_authentication/options/index.html.erb index 6983bca9aba..63d8d8ab883 100644 --- a/app/views/two_factor_authentication/options/index.html.erb +++ b/app/views/two_factor_authentication/options/index.html.erb @@ -8,6 +8,12 @@ <%= @presenter.info %>

+<% if @presenter.restricted_options_warning_text.present? %> + <%= render AlertComponent.new(type: :warning, class: 'margin-top-4') do %> + <%= @presenter.restricted_options_warning_text %> + <% end %> +<% end %> + <%= simple_form_for( @two_factor_options_form, html: { autocomplete: 'off' }, diff --git a/app/views/two_factor_authentication/piv_cac_verification/show.html.erb b/app/views/two_factor_authentication/piv_cac_verification/show.html.erb index b1938bb4afb..2608296466a 100644 --- a/app/views/two_factor_authentication/piv_cac_verification/show.html.erb +++ b/app/views/two_factor_authentication/piv_cac_verification/show.html.erb @@ -3,7 +3,7 @@ <%= render PageHeadingComponent.new.with_content(@presenter.header) %>

- <%= @presenter.piv_cac_help %> + <%= t('instructions.mfa.piv_cac.confirm_piv_cac') %>

diff --git a/config/locales/instructions/en.yml b/config/locales/instructions/en.yml index b09dda48ba9..b414a32ed19 100644 --- a/config/locales/instructions/en.yml +++ b/config/locales/instructions/en.yml @@ -37,12 +37,6 @@ en: you think this is an error, %{try_again_html}. back_to_sign_in: Go back to sign in confirm_piv_cac: Present the PIV/CAC that you associated with your account. - confirm_piv_cac_only: This app requires a higher level of security. You need to - verify your identity using a government employee ID that you - previously set up to access your information. - confirm_piv_cac_or_aal3: This app requires a higher level of security. You need - to verify your identity using a physical device such as a security key - or government employee ID (PIV or CAC) to access your information. did_not_work_html: Please %{please_try_again_html}. If this problem continues, contact your agency administrator. http_failure: The server took too long to respond. Please try again. @@ -72,12 +66,6 @@ en: code will expire in %{expiration} minutes. webauthn: confirm_webauthn: Present the security key that you associated with your account. - confirm_webauthn_only: This app requires a higher level of security. You need to - verify your identity using a security key that you previously set up - to access your information. - confirm_webauthn_or_aal3: This app requires a higher level of security. You need - to verify your identity using a physical device such as a security key - or government employee ID (PIV or CAC) to access your information. confirm_webauthn_platform: You have face or touch unlock enabled for your %{app_name} account. webauthn_platform: learn_more_help: Learn more about face or touch unlock diff --git a/config/locales/instructions/es.yml b/config/locales/instructions/es.yml index d98d0e83add..e18e74d0dd2 100644 --- a/config/locales/instructions/es.yml +++ b/config/locales/instructions/es.yml @@ -39,13 +39,6 @@ es: día. Si cree que se trata de un error, %{try_again_html}. back_to_sign_in: Regrese para iniciar sesión confirm_piv_cac: Presenta la PIV/CAC que asociaste con tu cuenta. - confirm_piv_cac_only: Esta aplicación requiere un mayor nivel de seguridad. Debe - verificar su identidad con una identificación de empleado del Gobierno - que haya configurado previamente para acceder a su información. - confirm_piv_cac_or_aal3: Esta aplicación requiere un mayor nivel de seguridad. - Debe verificar su identidad con un dispositivo físico, como una llave - de seguridad o una identificación de empleado del Gobierno (PIV o CAC) - para acceder a su información. did_not_work_html: '%{please_try_again_html}. Comuníquese con el encargado de su organismo si persiste este problema.' http_failure: El servidor tardó demasiado en responder. Inténtalo de nuevo. @@ -75,13 +68,6 @@ es: %{number_html}. Este código expirará en %{expiration} minutos. webauthn: confirm_webauthn: Presente la clave de seguridad que asoció con su cuenta. - confirm_webauthn_only: Esta aplicación requiere un mayor nivel de seguridad. - Debe verificar su identidad con una llave de seguridad que haya - configurado previamente para acceder a su información. - confirm_webauthn_or_aal3: Esta aplicación requiere un mayor nivel de seguridad. - Debe verificar su identidad con un dispositivo físico, como una llave - de seguridad o una identificación de empleado del Gobierno (PIV o CAC) - para acceder a su información. confirm_webauthn_platform: Tiene activado el desbloqueo facial o táctil para su cuenta de %{app_name}. webauthn_platform: diff --git a/config/locales/instructions/fr.yml b/config/locales/instructions/fr.yml index 15a7213007c..dddca997dd2 100644 --- a/config/locales/instructions/fr.yml +++ b/config/locales/instructions/fr.yml @@ -45,14 +45,6 @@ fr: back_to_sign_in: Retourner à vous connecter confirm_piv_cac: Veuillez présenter la carte PIV/CAC que vous avez associée à votre compte. - confirm_piv_cac_only: Cette application nécessite un niveau de sécurité plus - élevé. Vous devez vérifier votre identité à l’aide d’un badge - d’employé du gouvernement que vous avez précédemment configuré pour - accéder à vos informations. - confirm_piv_cac_or_aal3: Cette application nécessite un niveau de sécurité plus - élevé. Vous devez vérifier votre identité à l’aide d’un dispositif - physique tel qu’une clé de sécurité ou un badge d’employé du - gouvernement (PIV ou CAC) pour accéder à vos informations. did_not_work_html: Veuillez %{please_try_again_html}. Si ce problème persiste, contactez l’administrateur de votre agence. http_failure: Le serveur a mis trop de temps à répondre. Veuillez réessayer. @@ -85,14 +77,6 @@ fr: %{number_html}. Ce code expirera dans %{expiration} minutes. webauthn: confirm_webauthn: Présentez la clé de sécurité associée à votre compte. - confirm_webauthn_only: Cette application nécessite un niveau de sécurité plus - élevé. Vous devez vérifier votre identité à l’aide d’une clé de - sécurité que vous avez précédemment configurée pour accéder à vos - informations. - confirm_webauthn_or_aal3: Cette application nécessite un niveau de sécurité plus - élevé. Vous devez vérifier votre identité à l’aide d’un dispositif - physique tel qu’une clé de sécurité ou un badge d’employé du - gouvernement (PIV ou CAC) pour accéder à vos informations. confirm_webauthn_platform: Vous avez activé le déverrouillage facial ou tactile pour votre compte %{app_name}. webauthn_platform: diff --git a/config/locales/two_factor_authentication/en.yml b/config/locales/two_factor_authentication/en.yml index 047133f4f0e..aef059683ee 100644 --- a/config/locales/two_factor_authentication/en.yml +++ b/config/locales/two_factor_authentication/en.yml @@ -1,6 +1,12 @@ --- en: two_factor_authentication: + aal2_request: + phishing_resistant_html: '%{sp_name} requires a high-security + authentication method, such as face or touch unlock, a security key or a + government employee ID.' + piv_cac_only_html: '%{sp_name} requires your government + employee ID, a high-security authentication method.' account_reset: cancel_link: Cancel your request link: deleting your account @@ -124,7 +130,6 @@ en: change_number: Use another phone number code_not_received: I didn’t receive my one-time code piv_cac_header_text: Present your PIV/CAC - piv_cac_webauthn_available: Use your security key please_try_again_html: Please try again in %{countdown}. read_about_two_factor_authentication: Read about two-factor authentication recaptcha: @@ -178,7 +183,6 @@ en: additional_methods_link: choose another authentication method try_again: Face or touch unlock was unsuccessful. Please try again or %{link}. webauthn_header_text: Connect your security key - webauthn_piv_available: Use your PIV or CAC webauthn_platform_header_text: Use face or touch unlock webauthn_platform_use_key: Use face or touch unlock webauthn_use_key: Use security key diff --git a/config/locales/two_factor_authentication/es.yml b/config/locales/two_factor_authentication/es.yml index 86482e50eb4..d597d6d7673 100644 --- a/config/locales/two_factor_authentication/es.yml +++ b/config/locales/two_factor_authentication/es.yml @@ -1,6 +1,12 @@ --- es: two_factor_authentication: + aal2_request: + phishing_resistant_html: '%{sp_name} requiere un método de + autenticación de alta seguridad, como el desbloqueo facial o táctil, una + llave de seguridad o una identificación de empleado público.' + piv_cac_only_html: '%{sp_name} requiere su identificación de + empleado público, un método de autenticación de alta seguridad.' account_reset: cancel_link: Cancelar su solicitud link: eliminando su cuenta @@ -132,7 +138,6 @@ es: change_number: Utilice otro número de teléfono. code_not_received: No recibí mi código de un solo uso. piv_cac_header_text: Presenta tu PIV/CAC - piv_cac_webauthn_available: Utilice su llave de seguridad please_try_again_html: Inténtelo de nuevo en %{countdown}. read_about_two_factor_authentication: Conozca la autenticación de dos factores recaptcha: @@ -193,7 +198,6 @@ es: try_again: El desbloqueo facial o táctil no fue exitoso. Por favor, inténtelo de nuevo o %{link}. webauthn_header_text: Conecte su llave de seguridad - webauthn_piv_available: Utilice su PIV o CAC webauthn_platform_header_text: Usar desbloqueo facial o táctil webauthn_platform_use_key: Usar desbloqueo facial o táctil webauthn_use_key: Usar llave de seguridad diff --git a/config/locales/two_factor_authentication/fr.yml b/config/locales/two_factor_authentication/fr.yml index 8701f807602..040cb780cf4 100644 --- a/config/locales/two_factor_authentication/fr.yml +++ b/config/locales/two_factor_authentication/fr.yml @@ -1,6 +1,14 @@ --- fr: two_factor_authentication: + aal2_request: + phishing_resistant_html: '%{sp_name} nécessite une méthode + d’authentification de haute sécurité, telle que le déverrouillage du + visage ou du tactile, une clé de sécurité ou un identifiant d’employé du + gouvernement.' + piv_cac_only_html: '%{sp_name} nécessite votre identifiant + d’employé du gouvernement, une méthode d’authentification de haute + sécurité.' account_reset: cancel_link: Annuler votre demande link: supprimer votre compte @@ -138,7 +146,6 @@ fr: change_number: Utilisez un autre numéro de téléphone code_not_received: Je n’ai pas reçu mon code à usage unique piv_cac_header_text: Veuillez présenter votre carte PIV/CAC - piv_cac_webauthn_available: Utilisez votre clé de sécurité please_try_again_html: Veuillez essayer de nouveau dans %{countdown}. read_about_two_factor_authentication: En savoir plus sur l’authentification à deux facteurs recaptcha: @@ -199,7 +206,6 @@ fr: try_again: Le déverrouillage facial ou tactile n’a pas fonctionné. Veuillez réessayer ou %{link}. webauthn_header_text: Connectez votre clé de sécurité - webauthn_piv_available: Utilisez votre PIV ou CAC webauthn_platform_header_text: Utilisez le déverrouillage facial ou tactile webauthn_platform_use_key: Utilisez le déverrouillage facial ou tactile webauthn_use_key: Utiliser la clé de sécurité diff --git a/spec/policies/service_provider_mfa_policy_spec.rb b/spec/policies/service_provider_mfa_policy_spec.rb index f16cc9ab66e..8a30d8a1ee7 100644 --- a/spec/policies/service_provider_mfa_policy_spec.rb +++ b/spec/policies/service_provider_mfa_policy_spec.rb @@ -197,61 +197,6 @@ end end - describe '#allow_user_to_switch_method?' do - context 'phishing-resistant required' do - let(:aal_level_requested) { 3 } - - context 'the user has more than one phishing-resistant method' do - before do - setup_user_webauthn_token - setup_user_piv - end - - it { expect(policy.allow_user_to_switch_method?).to eq(true) } - end - - context 'the user does not have more than one aal3 method' do - before do - setup_user_webauthn_token - end - - it { expect(policy.allow_user_to_switch_method?).to eq(false) } - end - end - - context 'piv/cac required' do - let(:aal_level_requested) { 3 } - let(:piv_cac_requested) { true } - - context 'the user has a PIV' do - before { setup_user_piv } - - it { expect(policy.allow_user_to_switch_method?).to eq(false) } - end - - context 'the user does not have a PIV' do - before { setup_user_webauthn_token } - - it { expect(policy.allow_user_to_switch_method?).to eq(false) } - end - - context 'the user has a PIV and webauthn token' do - before do - setup_user_webauthn_token - setup_user_piv - end - - it { expect(policy.allow_user_to_switch_method?).to eq(false) } - end - end - - context 'there are no MFA reqirements' do - before { setup_user_phone } - - it { expect(policy.allow_user_to_switch_method?).to eq(true) } - end - end - def setup_user_phone user.phone_configurations << build(:phone_configuration) user.save! diff --git a/spec/presenters/two_factor_auth_code/generic_delivery_presenter_spec.rb b/spec/presenters/two_factor_auth_code/generic_delivery_presenter_spec.rb index 348c8621eeb..62ec8588ee5 100644 --- a/spec/presenters/two_factor_auth_code/generic_delivery_presenter_spec.rb +++ b/spec/presenters/two_factor_auth_code/generic_delivery_presenter_spec.rb @@ -19,26 +19,13 @@ c.content == t('two_factor_authentication.login_options_link_text') end expect(presenter.troubleshooting_options[1]).to satisfy do |c| - c.content == t('two_factor_authentication.learn_more') && c.new_tab? - end - end - - context 'with blank link path' do - before do - allow(presenter).to receive(:link_path).and_return('') - end - - it 'includes default troubleshooting options' do - expect(presenter.troubleshooting_options.size).to eq(1) - expect(presenter.troubleshooting_options[0]).to satisfy do |c| + c.content == t('two_factor_authentication.learn_more') && c.new_tab? && - c.content == t('two_factor_authentication.learn_more') && - c.url == help_center_redirect_path( - category: 'get-started', - article: 'authentication-options', - flow: :two_factor_authentication, - ) - end + c.url == help_center_redirect_path( + category: 'get-started', + article: 'authentication-options', + flow: :two_factor_authentication, + ) end end end diff --git a/spec/presenters/two_factor_auth_code/piv_cac_authentication_presenter_spec.rb b/spec/presenters/two_factor_auth_code/piv_cac_authentication_presenter_spec.rb index 55b49b5be80..2f73a7e8da2 100644 --- a/spec/presenters/two_factor_auth_code/piv_cac_authentication_presenter_spec.rb +++ b/spec/presenters/two_factor_auth_code/piv_cac_authentication_presenter_spec.rb @@ -8,7 +8,6 @@ let(:reauthn) {} let(:presenter) { presenter_with(reauthn: reauthn) } - let(:allow_user_to_switch_method) { false } let(:phishing_resistant_required) { true } let(:piv_cac_required) { false } let(:service_provider_mfa_policy) do @@ -16,7 +15,6 @@ ServiceProviderMfaPolicy, phishing_resistant_required?: phishing_resistant_required, piv_cac_required?: piv_cac_required, - allow_user_to_switch_method?: allow_user_to_switch_method, ) end @@ -32,117 +30,6 @@ it { expect(presenter.header).to eq expected_header } end - describe '#piv_cac_help' do - let(:phishing_resistant_required) { false } - let(:piv_cac_required) { false } - - it 'returns help text' do - expect(presenter.piv_cac_help).to eq(t('instructions.mfa.piv_cac.confirm_piv_cac')) - end - - context 'with PIV/CAC only requested' do - let(:phishing_resistant_required) { true } - let(:piv_cac_required) { true } - - context 'with a user who only has a PIV' do - let(:allow_user_to_switch_method) { false } - - it 'returns the PIV only help text' do - expect(presenter.piv_cac_help).to eq( - t('instructions.mfa.piv_cac.confirm_piv_cac_only'), - ) - end - end - - context 'with a user who has a PIV and security key' do - let(:allow_user_to_switch_method) { false } - - it 'returns the PIV only help text' do - expect(presenter.piv_cac_help).to eq( - t('instructions.mfa.piv_cac.confirm_piv_cac_only'), - ) - end - end - end - - context 'with phishing-resistant requested' do - let(:phishing_resistant_required) { true } - let(:piv_cac_required) { false } - - context 'with a user who only has a PIV' do - let(:allow_user_to_switch_method) { false } - - it 'returns the PIV only help text' do - expect(presenter.piv_cac_help).to eq( - t('instructions.mfa.piv_cac.confirm_piv_cac_only'), - ) - end - end - - context 'with a user who has a PIV and security key' do - let(:allow_user_to_switch_method) { true } - - it 'returns the PIV or phishing-resistant help text' do - expect(presenter.piv_cac_help).to eq( - t('instructions.mfa.piv_cac.confirm_piv_cac_or_aal3'), - ) - end - end - end - end - - describe '#link_text' do - let(:phishing_resistant_required) { true } - - context 'with multiple phishing-resistant methods' do - let(:allow_user_to_switch_method) { true } - - it 'supplies link text' do - expect(presenter.link_text).to eq(t('two_factor_authentication.piv_cac_webauthn_available')) - end - end - context 'with only one phishing-resistant method do' do - let(:allow_user_to_switch_method) { false } - - it ' supplies no link text' do - expect(presenter.link_text).to eq('') - end - end - end - - describe '#troubleshooting_options' do - context 'when the user can switch to a different method' do - let(:allow_user_to_switch_method) { true } - let(:phishing_resistant_required) { false } - - it 'includes option to choose another authentication method' do - expect(presenter.troubleshooting_options.size).to eq(2) - expect(presenter.troubleshooting_options.first).to satisfy do |c| - c.url == login_two_factor_options_path && - c.content == t('two_factor_authentication.login_options_link_text') - end - end - - context 'when phishing resistant method is required' do - let(:phishing_resistant_required) { true } - - it 'includes option to use another phishing resistant method' do - expect(presenter.troubleshooting_options.size).to eq(2) - expect(presenter.troubleshooting_options.first).to satisfy do |c| - c.url == login_two_factor_webauthn_url && - c.content == t('two_factor_authentication.piv_cac_webauthn_available') - end - end - end - end - - context 'when the user cannot switch to a different method' do - let(:allow_user_to_switch_method) { false } - - it { expect(presenter.troubleshooting_options.size).to eq(1) } - end - end - describe '#piv_cac_capture_text' do let(:expected_text) { t('forms.piv_cac_mfa.submit') } diff --git a/spec/presenters/two_factor_auth_code/webauthn_authentication_presenter_spec.rb b/spec/presenters/two_factor_auth_code/webauthn_authentication_presenter_spec.rb index 51f6cadf39a..c5bc98967cf 100644 --- a/spec/presenters/two_factor_auth_code/webauthn_authentication_presenter_spec.rb +++ b/spec/presenters/two_factor_auth_code/webauthn_authentication_presenter_spec.rb @@ -15,7 +15,6 @@ ) end - let(:allow_user_to_switch_method) { false } let(:phishing_resistant_required) { false } let(:platform_authenticator) { false } let(:multiple_factors_enabled) { false } @@ -23,7 +22,6 @@ instance_double( ServiceProviderMfaPolicy, phishing_resistant_required?: phishing_resistant_required, - allow_user_to_switch_method?: allow_user_to_switch_method, multiple_factors_enabled?: multiple_factors_enabled, ) end @@ -33,38 +31,10 @@ end describe '#webauthn_help' do - context 'with phishing-resistant required' do - let(:phishing_resistant_required) { true } + let(:phishing_resistant_required) { false } - context 'the user only has a security key enabled' do - let(:allow_user_to_switch_method) { false } - - it 'returns the help text for just the security key' do - expect(presenter.webauthn_help).to eq( - t('instructions.mfa.webauthn.confirm_webauthn_only'), - ) - end - end - - context 'the user has a security key and PIV enabled' do - let(:allow_user_to_switch_method) { true } - - it 'returns the help text for the security key or PIV' do - expect(presenter.webauthn_help).to eq( - t('instructions.mfa.webauthn.confirm_webauthn_or_aal3'), - ) - end - end - end - - context 'with phishing-resistant not required' do - let(:phishing_resistant_required) { false } - - it 'displays the help text' do - expect(presenter.webauthn_help).to eq( - t('instructions.mfa.webauthn.confirm_webauthn'), - ) - end + it 'returns the help text for security key' do + expect(presenter.webauthn_help).to eq(t('instructions.mfa.webauthn.confirm_webauthn')) end context 'with a platform authenticator' do @@ -137,67 +107,27 @@ end end - describe '#link_text' do - let(:phishing_resistant_required) { true } - - context 'with multiple phishing-resistant methods' do - let(:allow_user_to_switch_method) { true } - - it 'supplies link text' do - expect(presenter.link_text).to eq(t('two_factor_authentication.webauthn_piv_available')) - end - end - - context 'with only one phishing-resistant method do' do - it 'supplies no link text' do - expect(presenter.link_text).to eq('') - end - end - end - describe '#troubleshooting_options' do - context 'when the user can switch to a different method' do - let(:allow_user_to_switch_method) { true } - let(:phishing_resistant_required) { false } - - it 'includes option to choose another authentication method' do - expect(presenter.troubleshooting_options.size).to eq(2) - expect(presenter.troubleshooting_options.first).to satisfy do |c| - c.url == login_two_factor_options_path && - c.content == t('two_factor_authentication.login_options_link_text') - end - end + let(:phishing_resistant_required) { false } - context 'with platform authenticator' do - let(:platform_authenticator) { true } - - it 'includes option to learn more about face or touch unlock' do - expect(presenter.troubleshooting_options.size).to eq(3) - expect(presenter.troubleshooting_options[1]).to satisfy do |c| - c.content == t('instructions.mfa.webauthn_platform.learn_more_help') - end - end + it 'includes option to choose another authentication method' do + expect(presenter.troubleshooting_options.size).to eq(2) + expect(presenter.troubleshooting_options.first).to satisfy do |c| + c.url == login_two_factor_options_path && + c.content == t('two_factor_authentication.login_options_link_text') end + end - context 'when phishing resistant method is required' do - let(:phishing_resistant_required) { true } + context 'with platform authenticator' do + let(:platform_authenticator) { true } - it 'includes option to use another phishing resistant method' do - expect(presenter.troubleshooting_options.size).to eq(2) - expect(presenter.troubleshooting_options.first).to satisfy do |c| - c.url == login_two_factor_piv_cac_url && - c.content == t('two_factor_authentication.webauthn_piv_available') - end + it 'includes option to learn more about face or touch unlock' do + expect(presenter.troubleshooting_options.size).to eq(3) + expect(presenter.troubleshooting_options[1]).to satisfy do |c| + c.content == t('instructions.mfa.webauthn_platform.learn_more_help') end end end - - context 'when the user cannot switch to a different method' do - let(:allow_user_to_switch_method) { false } - let(:phishing_resistant_required) { true } - - it { expect(presenter.troubleshooting_options.size).to eq(1) } - end end describe '#cancel_link' do diff --git a/spec/presenters/two_factor_login_options_presenter_spec.rb b/spec/presenters/two_factor_login_options_presenter_spec.rb index 576a363ece6..926e6204f88 100644 --- a/spec/presenters/two_factor_login_options_presenter_spec.rb +++ b/spec/presenters/two_factor_login_options_presenter_spec.rb @@ -8,15 +8,16 @@ let(:phishing_resistant_required) { false } let(:piv_cac_required) { false } let(:reauthentication_context) { false } + let(:service_provider) { nil } subject(:presenter) do TwoFactorLoginOptionsPresenter.new( user: user, view: view, reauthentication_context: reauthentication_context, - service_provider: nil, - phishing_resistant_required: false, - piv_cac_required: false, + service_provider: service_provider, + phishing_resistant_required: phishing_resistant_required, + piv_cac_required: piv_cac_required, ) end @@ -75,6 +76,81 @@ end end + describe '#restricted_options_warning_text' do + subject(:restricted_options_warning_text) { presenter.restricted_options_warning_text } + + it { should be_nil } + + context 'phishing resistant required' do + let(:phishing_resistant_required) { true } + + it 'returns phishing resistant required warning text for app' do + expect(restricted_options_warning_text).to eq( + t('two_factor_authentication.aal2_request.phishing_resistant_html', sp_name: APP_NAME), + ) + end + + context 'piv cac required' do + let(:piv_cac_required) { true } + + it 'returns piv cac required warning text for app' do + expect(restricted_options_warning_text).to eq( + t('two_factor_authentication.aal2_request.piv_cac_only_html', sp_name: APP_NAME), + ) + end + + context 'with sp' do + let(:service_provider) { build(:service_provider) } + + it 'returns piv cac required warning text for service provider' do + expect(restricted_options_warning_text).to eq( + t( + 'two_factor_authentication.aal2_request.piv_cac_only_html', + sp_name: service_provider.friendly_name, + ), + ) + end + end + end + + context 'with sp' do + let(:service_provider) { build(:service_provider) } + + it 'returns phishing resistant required warning text for service provider' do + expect(restricted_options_warning_text).to eq( + t( + 'two_factor_authentication.aal2_request.phishing_resistant_html', + sp_name: service_provider.friendly_name, + ), + ) + end + end + end + + context 'piv cac required' do + let(:piv_cac_required) { true } + + it 'returns piv cac required warning text for app' do + expect(restricted_options_warning_text).to eq( + t('two_factor_authentication.aal2_request.piv_cac_only_html', sp_name: APP_NAME), + ) + end + + context 'with sp' do + let(:service_provider) { build(:service_provider) } + + it 'returns piv cac required warning text for service provider' do + expect(restricted_options_warning_text).to eq( + t( + 'two_factor_authentication.aal2_request.piv_cac_only_html', + sp_name: service_provider.friendly_name, + ), + ) + end + end + end + end + describe '#cancel_link' do subject(:cancel_link) { presenter.cancel_link } diff --git a/spec/views/two_factor_authentication/options/index.html.erb_spec.rb b/spec/views/two_factor_authentication/options/index.html.erb_spec.rb index e418a0a30a1..929a427f88d 100644 --- a/spec/views/two_factor_authentication/options/index.html.erb_spec.rb +++ b/spec/views/two_factor_authentication/options/index.html.erb_spec.rb @@ -2,6 +2,9 @@ RSpec.describe 'two_factor_authentication/options/index.html.erb' do let(:user) { User.new } + let(:phishing_resistant_required) { false } + let(:piv_cac_required) { false } + before do allow(view).to receive(:user_session).and_return({}) allow(view).to receive(:current_user).and_return(User.new) @@ -11,8 +14,8 @@ view: view, reauthentication_context: false, service_provider: nil, - phishing_resistant_required: false, - piv_cac_required: false, + phishing_resistant_required: phishing_resistant_required, + piv_cac_required: piv_cac_required, ) @two_factor_options_form = TwoFactorLoginOptionsForm.new(user) end @@ -64,4 +67,34 @@ ) end end + + context 'with phishing resistant required' do + let(:phishing_resistant_required) { true } + + before { render } + + it 'displays warning text' do + expect(rendered).to have_selector( + '.usa-alert.usa-alert--warning', + text: strip_tags( + t('two_factor_authentication.aal2_request.phishing_resistant_html', sp_name: APP_NAME), + ), + ) + end + end + + context 'with piv cac required' do + let(:piv_cac_required) { true } + + before { render } + + it 'displays warning text' do + expect(rendered).to have_selector( + '.usa-alert.usa-alert--warning', + text: strip_tags( + t('two_factor_authentication.aal2_request.piv_cac_only_html', sp_name: APP_NAME), + ), + ) + end + end end diff --git a/spec/views/two_factor_authentication/webauthn_verification/show.html.erb_spec.rb b/spec/views/two_factor_authentication/webauthn_verification/show.html.erb_spec.rb index 6379cc04f80..56ffa23f8d9 100644 --- a/spec/views/two_factor_authentication/webauthn_verification/show.html.erb_spec.rb +++ b/spec/views/two_factor_authentication/webauthn_verification/show.html.erb_spec.rb @@ -64,24 +64,4 @@ ) end end - - context 'with phishing-resistant MFA requirement' do - let(:phishing_resistant_required) { true } - - it 'does not include a troubleshooting link for using another MFA method' do - expect(rendered).to have_css('.troubleshooting-options li', count: 1) - end - - context 'with user having PIV/CAC configured' do - let(:user) { build(:user, :with_piv_or_cac, :with_webauthn) } - - it 'includes troubleshooting link to use PIV/CAC' do - expect(rendered).to have_css('.troubleshooting-options li', count: 2) - expect(rendered).to have_link( - t('two_factor_authentication.webauthn_piv_available'), - href: login_two_factor_piv_cac_url, - ) - end - end - end end