diff --git a/app/controllers/users/webauthn_setup_controller.rb b/app/controllers/users/webauthn_setup_controller.rb index fb76235571b..10a13ada6c8 100644 --- a/app/controllers/users/webauthn_setup_controller.rb +++ b/app/controllers/users/webauthn_setup_controller.rb @@ -14,7 +14,11 @@ class WebauthnSetupController < ApplicationController helper_method :in_multi_mfa_selection_flow? def new - form = WebauthnVisitForm.new(current_user) + form = WebauthnVisitForm.new( + user: current_user, + url_options: url_options, + in_mfa_selection_flow: in_multi_mfa_selection_flow?, + ) result = form.submit(new_params) @platform_authenticator = form.platform_authenticator? @presenter = WebauthnSetupPresenter.new( diff --git a/app/forms/webauthn_visit_form.rb b/app/forms/webauthn_visit_form.rb index 8b6bd82bcf6..35d07d83987 100644 --- a/app/forms/webauthn_visit_form.rb +++ b/app/forms/webauthn_visit_form.rb @@ -1,11 +1,17 @@ class WebauthnVisitForm include ActiveModel::Model + include ActionView::Helpers::UrlHelper + include Rails.application.routes.url_helpers + + attr_reader :url_options, :in_mfa_selection_flow INVALID_STATE_ERROR = 'InvalidStateError' NOT_SUPPORTED_ERROR = 'NotSupportedError' - def initialize(user) + def initialize(user:, url_options:, in_mfa_selection_flow:) @user = user + @url_options = url_options + @in_mfa_selection_flow = in_mfa_selection_flow end def submit(params) @@ -39,7 +45,17 @@ def translate_platform_authenticator_error(error) when NOT_SUPPORTED_ERROR I18n.t('errors.webauthn_platform_setup.not_supported') else - I18n.t('errors.webauthn_platform_setup.general_error') + if in_mfa_selection_flow + I18n.t( + 'errors.webauthn_platform_setup.account_setup_error', + link: link_to( + I18n.t('errors.webauthn_platform_setup.choose_another_method'), + authentication_methods_setup_path, + ), + ) + else + I18n.t('errors.webauthn_platform_setup.general_error') + end end end diff --git a/config/locales/errors/en.yml b/config/locales/errors/en.yml index f9a247cbb51..3600ddcd5c9 100644 --- a/config/locales/errors/en.yml +++ b/config/locales/errors/en.yml @@ -114,14 +114,16 @@ en: verify_profile: throttled: You tried too many times, please try again in %{timeout}. webauthn_platform_setup: - already_registered: Platform authenticator already registered. Please try a - different platform authenticator. + account_setup_error: We were unable to add face or touch unlock. Please try again or %{link}. + already_registered: Face or touch unlock is already registered on this device. + Please try adding another authentication method. attestation_error: Sorry, but your platform authenticator doesn’t appear to be a FIDO platform authenticator. Please make sure your device is listed at https://fidoalliance.org/certification/fido-certified-products/ and if you believe this is our error, please contact at %{link}. - general_error: There was an error adding your hardware platform authenticator. - Please try again. + choose_another_method: choose another authentication method + general_error: We were unable to add face or touch unlock. Please try again or + choose another method. not_supported: Sorry, your browser does not support FIDO platform authenticators. The latest versions of Chrome, Firefox, Edge, and Safari support FIDO platform authenticators. diff --git a/config/locales/errors/es.yml b/config/locales/errors/es.yml index b2b3f9a293e..80355dc3322 100644 --- a/config/locales/errors/es.yml +++ b/config/locales/errors/es.yml @@ -120,15 +120,19 @@ es: verify_profile: throttled: Lo intentaste muchas veces, vuelve a intentarlo en %{timeout}. webauthn_platform_setup: - already_registered: El desbloqueo facial o táctil ya está registrado. Por favor, - intente un método de plataforma diferente para iniciar la sesión. + account_setup_error: No pudimos agregar el desbloqueo con la cara o con la + huella digital. Inténtelo de nuevo o %{link}. + already_registered: Ya está registrado el desbloqueo con la cara o con la huella + digital en este dispositivo. Trate de agregar otro método de + autenticación. attestation_error: Lo sentimos, pero su desbloqueo facial o táctil no parece funcionar. Por favor, asegúrese de que su dispositivo está registrado en https://fidoalliance.org/certification/fido-certified-products/ y si cree que se trata de un error nuestro, póngase en contacto con nosotros en %{link}. - general_error: Se ha producido un error al agregar su método de autenticación. - Por favor, inténtelo de nuevo. + choose_another_method: elija otro método de autenticación + general_error: No pudimos agregar el desbloqueo con la cara o con la huella + digital. Inténtelo de nuevo o elija otro método de autenticación. not_supported: Lo sentimos, pero su navegador no es compatible con el desbloqueo facial o táctil. unique_name: Ese nombre de dispositivo ha sido utilizado. Por favor, seleccione diff --git a/config/locales/errors/fr.yml b/config/locales/errors/fr.yml index b7881210929..abe7843e95a 100644 --- a/config/locales/errors/fr.yml +++ b/config/locales/errors/fr.yml @@ -130,15 +130,20 @@ fr: verify_profile: throttled: Vous avez essayé plusieurs fois, essayez à nouveau dans %{timeout}. webauthn_platform_setup: - already_registered: Le déverrouillage facial ou tactile est déjà enregistré. - Veuillez essayer une autre méthode de plateforme pour vous connecter. + account_setup_error: Nous n’avons pas pu ajouter le déverrouillage facial ni le + déverrouillage tactile. Veuillez réessayer ou %{link}. + already_registered: Le déverrouillage facial ou le déverrouillage tactile est + déjà enregistré sur cet appareil. Veuillez essayer d’ajouter une autre + méthode d’authentification. attestation_error: Désolé, mais votre déverrouillage facial ou tactile ne semble pas fonctionner. Veuillez vous assurer que votre appareil est répertorié sur https://fidoalliance.org/certification/fido-certified-products/ et si vous pensez qu’il s’agit d’une erreur de notre part, veuillez nous contacter à %{link}. - general_error: Une erreur s’est produite lors de l’ajout de votre méthode - d’authentification. Veuillez réessayer. + choose_another_method: choisir une autre méthode d’authentification + general_error: Nous n’avons pas pu ajouter le déverrouillage facial ni le + déverrouillage tactile. Veuillez réessayer ou choisir une autre méthode + d’authentification. not_supported: Nous sommes désolés, mais votre navigateur ne prend pas en charge le déverrouillage du visage ou du toucher. unique_name: Ce nom d’appareil a été utilisé. Veuillez sélectionner un autre nom diff --git a/spec/forms/webauthn_visit_form_spec.rb b/spec/forms/webauthn_visit_form_spec.rb index a9554e569c0..c2d32412e9c 100644 --- a/spec/forms/webauthn_visit_form_spec.rb +++ b/spec/forms/webauthn_visit_form_spec.rb @@ -1,8 +1,18 @@ require 'rails_helper' RSpec.describe WebauthnVisitForm do + include ActionView::Helpers::UrlHelper + include Rails.application.routes.url_helpers + let(:user) { build(:user) } - let(:subject) { WebauthnVisitForm.new(user) } + let(:url_options) { {} } + let(:subject) do + WebauthnVisitForm.new( + user: user, + url_options:, + in_mfa_selection_flow: true, + ) + end describe '#submit' do it 'returns FormResponse with success: true if there are no errors' do @@ -90,7 +100,13 @@ it 'returns FormResponse with success: false with an unrecognized error' do params = { error: 'foo', platform: 'true' } - errors = { foo: [I18n.t('errors.webauthn_platform_setup.general_error')] } + errors = { foo: [I18n.t( + 'errors.webauthn_platform_setup.account_setup_error', + link: link_to( + I18n.t('errors.webauthn_platform_setup.choose_another_method'), + authentication_methods_setup_path, + ), + )] } expect(subject.submit(params).to_h).to include( success: false, @@ -98,6 +114,29 @@ error_details: hash_including(*errors.keys), ) end + + context 'when a user is not in mfa selection' do + let(:subject) do + WebauthnVisitForm.new( + user: user, + url_options: {}, + in_mfa_selection_flow: false, + ) + end + + it 'returns FormResponse with success: false with an unrecognized error' do + params = { error: 'foo', platform: 'true' } + errors = { foo: [I18n.t( + 'errors.webauthn_platform_setup.general_error', + )] } + + expect(subject.submit(params).to_h).to include( + success: false, + errors: errors, + error_details: hash_including(*errors.keys), + ) + end + end end end end