diff --git a/config/application.yml.default b/config/application.yml.default
index abb8196fde2..d3f67d63095 100644
--- a/config/application.yml.default
+++ b/config/application.yml.default
@@ -107,7 +107,6 @@ idv_max_attempts: 5
idv_min_age_years: 13
idv_native_camera_a_b_testing_enabled: false
idv_native_camera_a_b_testing_percent: 10
-idv_personal_key_confirmation_enabled: true
idv_send_link_attempt_window_in_minutes: 10
idv_send_link_max_attempts: 5
idv_sp_required: false
diff --git a/config/locales/components/es.yml b/config/locales/components/es.yml
index 24dcb36389f..014b65732fb 100644
--- a/config/locales/components/es.yml
+++ b/config/locales/components/es.yml
@@ -35,7 +35,7 @@ es:
phone_input:
country_code_label: Código del país
print_button:
- label: Imprima esta página
+ label: Imprima
troubleshooting_options:
default_heading: '¿Tiene alguna dificultad? Esto es lo que puede hacer:'
new_feature: Nueva función
diff --git a/config/locales/components/fr.yml b/config/locales/components/fr.yml
index e1be7225778..f0fc3a76998 100644
--- a/config/locales/components/fr.yml
+++ b/config/locales/components/fr.yml
@@ -35,7 +35,7 @@ fr:
phone_input:
country_code_label: Code pays
print_button:
- label: Imprimer cette page
+ label: Imprimer
troubleshooting_options:
default_heading: 'Des difficultés? Voici ce que vous pouvez faire:'
new_feature: Nouvelle fonction
diff --git a/config/locales/forms/en.yml b/config/locales/forms/en.yml
index 4478278956a..58f19630556 100644
--- a/config/locales/forms/en.yml
+++ b/config/locales/forms/en.yml
@@ -66,8 +66,27 @@ en:
personal_key:
alternative: Don’t have your personal key?
confirmation_label: Personal key
+ download: Download (text file)
instructions: Please confirm you have a copy of your personal key by entering it below.
+ required_checkbox: Please check this box to continue.
title: Enter your personal key
+ personal_key_partial:
+ acknowledgement:
+ bullets:
+ - You’ll lose access to your account
+ - You’ll need to verify your identity again
+ header: You need your personal key if you forget your password. Keep it safe and
+ don’t share it with anyone.
+ text: 'If you reset your password without your personal key:'
+ explanation:
+ header: What is a personal key?
+ text:
+ - A personal key “locks” your personal information with your account.
+ It’s the only way to unlock your information if you lose or forget
+ your password.
+ - When you reset your password, Login.gov will ask for your personal
+ key to make sure you are you - not someone pretending to be you.
+ header: Save your personal key
phone:
buttons:
delete: Remove phone
diff --git a/config/locales/forms/es.yml b/config/locales/forms/es.yml
index 4d449c235a5..10027a2e992 100644
--- a/config/locales/forms/es.yml
+++ b/config/locales/forms/es.yml
@@ -71,9 +71,29 @@ es:
personal_key:
alternative: '¿No tiene su clave personal?'
confirmation_label: Clave personal
+ download: Descargar (archivo de texto)
instructions: Confirme que tiene una copia de su clave personal ingresándola a
continuación.
+ required_checkbox: Marque esta casilla para continuar.
title: Ingrese su clave personal
+ personal_key_partial:
+ acknowledgement:
+ bullets:
+ - Perderás el acceso a tu cuenta
+ - Tendrás que verificar tu identidad nuevamente
+ header: Necesitarás tu clave personal si olvidas tu contraseña. Mantenla en un
+ lugar seguro y no la compartas con nadie.
+ text: 'Si restableces tu contraseña sin tu clave personal:'
+ explanation:
+ header: ¿Qué es una clave personal?
+ text:
+ - Una clave personal “bloquea” la información personal de tu cuenta.
+ Es la única manera de desbloquear tu información si pierdes u
+ olvidas tu contraseña.
+ - Si restableces tu contraseña, Login.gov te pedirá tu clave personal
+ para asegurarse de que se trata de ti, y no de alguien que quiere
+ hacerse pasar por ti.
+ header: Guarda tu clave personal
phone:
buttons:
delete: Eliminar el teléfono
diff --git a/config/locales/forms/fr.yml b/config/locales/forms/fr.yml
index 97cb4bd26ff..8035ab42d0b 100644
--- a/config/locales/forms/fr.yml
+++ b/config/locales/forms/fr.yml
@@ -72,9 +72,29 @@ fr:
personal_key:
alternative: Vous n’avez pas votre clé personnelle?
confirmation_label: Clé personnelle
+ download: Télécharger (fichier texte)
instructions: Veuillez confirmer que vous avez une copie de votre clé
personnelle en l’entrant ci-dessous.
+ required_checkbox: Veuillez cocher cette case pour continuer.
title: Entrez votre clé personnelle
+ personal_key_partial:
+ acknowledgement:
+ bullets:
+ - Vous perdrez l’accès à votre compte
+ - Vous allez devoir vérifier à nouveau votre identité
+ header: En cas d’oubli de votre mot de passe, vous aurez besoin de votre clé
+ personnelle. Gardez-la en sécurité et ne la partagez avec personne.
+ text: 'Si vous réinitialisez votre mot de passe sans votre clé personnelle:'
+ explanation:
+ header: Qu’est-ce qu’une clé personnelle?
+ text:
+ - Une clé personnelle « verrouille » vos informations personnelles
+ avec votre compte. C’est le seul moyen de déverrouiller vos
+ informations si vous perdez ou oubliez votre mot de passe.
+ - Lors de la réinitialisation de votre mot de passe, Login.gov vous
+ demandera votre clé personnelle pour s’assurer que vous êtes bien
+ vous, et non quelqu’un qui se fait passer pour vous.
+ header: Sauvegardez votre clé personnelle
phone:
buttons:
delete: Supprimer le numéro de teléfono
diff --git a/config/locales/headings/en.yml b/config/locales/headings/en.yml
index c19a456178e..aca5a659bc6 100644
--- a/config/locales/headings/en.yml
+++ b/config/locales/headings/en.yml
@@ -34,7 +34,6 @@ en:
confirm: Confirm your current password to continue
confirm_for_personal_key: Enter password and get a new personal key
forgot: Forgot your password?
- personal_key: Save your personal key
piv_cac:
certificate:
bad: The PIV/CAC certificate you selected is invalid
diff --git a/config/locales/headings/es.yml b/config/locales/headings/es.yml
index 01449e023fc..c8fc13dd168 100644
--- a/config/locales/headings/es.yml
+++ b/config/locales/headings/es.yml
@@ -34,7 +34,6 @@ es:
confirm: Confirme la contraseña actual para continuar
confirm_for_personal_key: Introduzca la contraseña y obtenga una nueva clave personal
forgot: '¿Olvidó su contraseña?'
- personal_key: Guarda tu clave personal
piv_cac:
certificate:
bad: El certificado PIV/CAC que seleccionaste no es válido.
diff --git a/config/locales/headings/fr.yml b/config/locales/headings/fr.yml
index de2c4e53066..c70bd3f926c 100644
--- a/config/locales/headings/fr.yml
+++ b/config/locales/headings/fr.yml
@@ -34,7 +34,6 @@ fr:
confirm: Confirmez votre mot de passe actuel pour continuer
confirm_for_personal_key: Entrez le mot de passe et obtenez une nouvelle clé personnelle
forgot: Vous avez oublié votre mot de passe?
- personal_key: Enregistrez votre clé personnelle
piv_cac:
certificate:
bad: Le certificat PIV/CAC que vous avez sélectionné n’est pas valide.
diff --git a/config/locales/instructions/en.yml b/config/locales/instructions/en.yml
index 9d3eae94ca6..abdf7e0763b 100644
--- a/config/locales/instructions/en.yml
+++ b/config/locales/instructions/en.yml
@@ -102,13 +102,6 @@ en:
intro: 'Password strength: '
iv: Good
v: Great!
- personal_key:
- email_body: Don’t lose your personal key or share it with others. We’ll ask for
- it if you reset your password.
- email_title: Save it. Keep it safe.
- info: You’ll need this personal key if you forget your password. If you reset
- your password and don’t have this key, you’ll have to verify your
- identity again.
sp_handoff_bounced: Your sign in was successful, but %{sp_name} sent you back to
%{app_name}. Please contact %{sp_link} for help.
sp_handoff_bounced_with_no_sp: your service provider
diff --git a/config/locales/instructions/es.yml b/config/locales/instructions/es.yml
index 9b1cfc800bb..bc2023c54a5 100644
--- a/config/locales/instructions/es.yml
+++ b/config/locales/instructions/es.yml
@@ -109,13 +109,6 @@ es:
intro: 'Seguridad de la contraseña:'
iv: Buena
v: '¡Muy buena!'
- personal_key:
- email_body: No pierdas tu clave personal ni la compartas con otros. La pediremos
- si restableces tu contraseña.
- email_title: Guárdala. Manténla segura.
- info: Necesitarás esta clave personal si olvidas tu contraseña. Si restableces
- tu contraseña y no tienes esta clave, deberás verificar tu identidad
- nuevamente.
sp_handoff_bounced: Su inicio de sesión fue exitoso, pero %{sp_name} lo envió de
regreso a %{app_name}. Póngase en contacto con %{sp_link} para obtener
ayuda.
diff --git a/config/locales/instructions/fr.yml b/config/locales/instructions/fr.yml
index 6cd6ae02317..71174ab25f4 100644
--- a/config/locales/instructions/fr.yml
+++ b/config/locales/instructions/fr.yml
@@ -119,14 +119,6 @@ fr:
intro: 'Force du mot de passe : '
iv: Bonne
v: Excellente!
- personal_key:
- email_body: Ne perdez pas votre clé personnelle et ne la partagez pas avec
- d’autres. Nous vous le demanderons si vous réinitialisez votre mot de
- passe.
- email_title: Sauvegarde le. Garde-le en sécurité.
- info: Vous aurez besoin de cette clé personnelle si vous oubliez votre mot de
- passe. Si vous réinitialisez votre mot de passe et que vous ne possédez
- pas cette clé, vous devrez vérifier votre identité à nouveau.
sp_handoff_bounced: Votre connexion a réussi, mais %{sp_name} vous a renvoyé à
%{app_name}. Veuillez contacter %{sp_link} pour obtenir de l’aide.
sp_handoff_bounced_with_no_sp: votre fournisseur de service
diff --git a/config/locales/users/en.yml b/config/locales/users/en.yml
index 378d09f4a02..316a6db802e 100644
--- a/config/locales/users/en.yml
+++ b/config/locales/users/en.yml
@@ -21,8 +21,7 @@ en:
personal_key:
close: Close
confirmation_error: You’ve entered an incorrect personal key.
- generated_on_html: Generated on %{date}
- header: Your personal key
+ generated_on_html: Your personal key was generated on %{date}
phones:
error_message: You’ve added the maximum number of phone numbers.
rules_of_use:
diff --git a/config/locales/users/es.yml b/config/locales/users/es.yml
index f1e8262854a..a883204cc8f 100644
--- a/config/locales/users/es.yml
+++ b/config/locales/users/es.yml
@@ -22,8 +22,7 @@ es:
personal_key:
close: Cerrar
confirmation_error: Ha ingresado una clave personal incorrecta.
- generated_on_html: Generado el %{date}
- header: Su clave personal
+ generated_on_html: Tu clave personal fue generada el %{date}
phones:
error_message: Agregó el número máximo de números de teléfono.
rules_of_use:
diff --git a/config/locales/users/fr.yml b/config/locales/users/fr.yml
index 1c17d049ae1..bbef10bd0f0 100644
--- a/config/locales/users/fr.yml
+++ b/config/locales/users/fr.yml
@@ -24,8 +24,7 @@ fr:
personal_key:
close: Fermer
confirmation_error: Vous avez entré un clé personnelle erronée.
- generated_on_html: Générée le %{date}
- header: Votre clé personnelle
+ generated_on_html: Votre clé personnelle a été générée le %{date}
phones:
error_message: Vous avez ajouté le nombre maximum de numéros de téléphone.
rules_of_use:
diff --git a/lib/feature_management.rb b/lib/feature_management.rb
index 4275487568b..a26e92bbe38 100644
--- a/lib/feature_management.rb
+++ b/lib/feature_management.rb
@@ -112,10 +112,6 @@ def self.log_to_stdout?
!Rails.env.test? && IdentityConfig.store.log_to_stdout
end
- def self.idv_personal_key_confirmation_enabled?
- IdentityConfig.store.idv_personal_key_confirmation_enabled
- end
-
# Manual allowlist for VOIPs, should only include known VOIPs that we use for smoke tests
# @return [Set] set of phone numbers normalized to e164
def self.voip_allowed_phones
diff --git a/lib/identity_config.rb b/lib/identity_config.rb
index 8f7ec34b0ea..d20424275c7 100644
--- a/lib/identity_config.rb
+++ b/lib/identity_config.rb
@@ -186,7 +186,6 @@ def self.build_store(config_map)
config.add(:idv_min_age_years, type: :integer)
config.add(:idv_native_camera_a_b_testing_enabled, type: :boolean)
config.add(:idv_native_camera_a_b_testing_percent, type: :integer)
- config.add(:idv_personal_key_confirmation_enabled, type: :boolean)
config.add(:idv_send_link_attempt_window_in_minutes, type: :integer)
config.add(:idv_send_link_max_attempts, type: :integer)
config.add(:idv_sp_required, type: :boolean)
diff --git a/spec/features/idv/analytics_spec.rb b/spec/features/idv/analytics_spec.rb
index 59f6413ab7d..573bb134ce1 100644
--- a/spec/features/idv/analytics_spec.rb
+++ b/spec/features/idv/analytics_spec.rb
@@ -39,7 +39,7 @@
'IdV: final resolution' => { success: true },
'IdV: personal key visited' => {},
'IdV: personal key submitted' => {},
- 'Frontend: IdV: show personal key modal' => {},
+ 'IdV: personal key acknowledgment toggled' => { checked: true },
}
end
let(:gpo_path_events) do
@@ -73,7 +73,6 @@
'IdV: review complete' => { success: true },
'IdV: final resolution' => { success: true },
'IdV: personal key visited' => {},
- 'Frontend: IdV: show personal key modal' => {},
'IdV: personal key submitted' => {},
'IdV: come back later visited' => {},
}
@@ -121,7 +120,6 @@
'IdV: review complete' => { success: true },
'IdV: final resolution' => { success: true },
'IdV: personal key visited' => {},
- 'Frontend: IdV: show personal key modal' => {},
'IdV: personal key submitted' => {},
'IdV: in person ready to verify visited' => {},
}
diff --git a/spec/features/idv/steps/confirmation_step_spec.rb b/spec/features/idv/steps/confirmation_step_spec.rb
index 9dd13ed6c6a..0052d2d5733 100644
--- a/spec/features/idv/steps/confirmation_step_spec.rb
+++ b/spec/features/idv/steps/confirmation_step_spec.rb
@@ -3,19 +3,14 @@
feature 'idv confirmation step', js: true do
include IdvStepHelper
- let(:idv_personal_key_confirmation_enabled) { true }
let(:sp) { nil }
let(:address_verification_mechanism) { :phone }
before do
- allow(IdentityConfig.store).to receive(:idv_personal_key_confirmation_enabled).
- and_return(idv_personal_key_confirmation_enabled)
start_idv_from_sp(sp)
complete_idv_steps_before_confirmation_step(address_verification_mechanism)
end
- it_behaves_like 'personal key page'
-
it 'shows status content for phone verification progress' do
expect(page).to have_content(t('idv.messages.confirm'))
expect_step_indicator_current_step(t('step_indicator.flows.idv.secure_account'))
@@ -29,7 +24,7 @@
it 'allows the user to refresh and still displays the personal key' do
# Visit the current path is the same as refreshing
visit current_path
- expect(page).to have_content(t('headings.personal_key'))
+ expect(page).to have_content(t('forms.personal_key_partial.acknowledgement.header'))
end
context 'verifying by gpo' do
@@ -41,13 +36,21 @@
expect(page).to have_content(t('step_indicator.flows.idv.get_a_letter'))
expect(page).not_to have_content(t('step_indicator.flows.idv.verify_phone_or_address'))
end
-
- it_behaves_like 'personal key page', :gpo
end
context 'with associated sp' do
let(:sp) { :oidc }
+ it "forces the user to click the 'acknowledge' checkbox before proceeding" do
+ click_continue
+
+ expect(page).to have_content(t('forms.validation.required_checkbox'))
+ expect(current_path).to eq(idv_personal_key_path)
+
+ acknowledge_and_confirm_personal_key
+ expect(page).to have_current_path(sign_up_completed_path)
+ end
+
it 'redirects to the completions page and then to the SP' do
acknowledge_and_confirm_personal_key
@@ -57,19 +60,5 @@
expect(current_url).to start_with('http://localhost:7654/auth/result')
end
-
- context 'with personal key confirmation disabled' do
- let(:idv_personal_key_confirmation_enabled) { false }
-
- it 'redirects to the completions page and then to the SP' do
- click_acknowledge_personal_key
-
- expect(page).to have_current_path(sign_up_completed_path)
-
- click_agree_and_continue
-
- expect(current_url).to start_with('http://localhost:7654/auth/result')
- end
- end
end
end
diff --git a/spec/features/idv/steps/review_step_spec.rb b/spec/features/idv/steps/review_step_spec.rb
index 652aabde783..3b90bd99784 100644
--- a/spec/features/idv/steps/review_step_spec.rb
+++ b/spec/features/idv/steps/review_step_spec.rb
@@ -32,7 +32,7 @@
fill_in 'Password', with: user_password
click_idv_continue
- expect(page).to have_content(t('headings.personal_key'))
+ expect(page).to have_content(t('forms.personal_key_partial.acknowledgement.header'))
expect(current_path).to eq idv_personal_key_path
end
diff --git a/spec/features/users/regenerate_personal_key_spec.rb b/spec/features/users/regenerate_personal_key_spec.rb
index 5a595988db2..135e09fd650 100644
--- a/spec/features/users/regenerate_personal_key_spec.rb
+++ b/spec/features/users/regenerate_personal_key_spec.rb
@@ -52,22 +52,11 @@
expect(page).to have_content(t('account.personal_key.get_new'))
click_continue
- expect(page).to have_content(t('headings.personal_key'))
+ expect(page).to have_content(t('forms.personal_key_partial.acknowledgement.header'))
acknowledge_and_confirm_personal_key
expect(user.reload.encrypted_recovery_code_digest).to_not eq old_digest
end
end
-
- describe 'personal key actions and information' do
- before do
- sign_in_and_2fa_user(user)
- visit account_two_factor_authentication_path
- click_on(t('account.links.regenerate_personal_key'), match: :prefer_exact)
- click_continue
- end
-
- it_behaves_like 'personal key page'
- end
end
end
diff --git a/spec/support/features/session_helper.rb b/spec/support/features/session_helper.rb
index d98d38b7a89..dc517a6b51c 100644
--- a/spec/support/features/session_helper.rb
+++ b/spec/support/features/session_helper.rb
@@ -318,12 +318,11 @@ def sign_in_with_totp_enabled_user
def acknowledge_and_confirm_personal_key
click_acknowledge_personal_key
-
- page.find(':focus').fill_in with: scrape_personal_key
- within('[role=dialog]') { click_continue }
end
def click_acknowledge_personal_key
+ checkbox_header = t('forms.validation.required_checkbox')
+ find('label', text: /#{checkbox_header}/).click
click_continue
end
diff --git a/spec/support/shared_examples_for_personal_keys.rb b/spec/support/shared_examples_for_personal_keys.rb
deleted file mode 100644
index c271dbdc0ed..00000000000
--- a/spec/support/shared_examples_for_personal_keys.rb
+++ /dev/null
@@ -1,85 +0,0 @@
-require 'rbconfig'
-
-shared_examples_for 'personal key page' do |address_verification_mechanism|
- include PersonalKeyHelper
- include JavascriptDriverHelper
-
- describe 'confirmation modal' do
- before do
- click_continue if javascript_enabled?
- end
-
- it 'displays modal content' do
- expect(page).to have_content t('forms.personal_key.title')
- expect(page).to have_content t('forms.personal_key.instructions')
- end
- end
-
- context 'with javascript enabled', js: true do
- before do
- page.driver.browser.execute_cdp(
- 'Browser.grantPermissions',
- origin: page.server_url,
- permissions: ['clipboardReadWrite', 'clipboardSanitizedWrite'],
- )
- end
-
- after do
- page.driver.browser.execute_cdp('Browser.resetPermissions')
- end
-
- it 'allows a user to copy the code into the confirmation modal' do
- click_on t('components.clipboard_button.label')
- copied_text = page.evaluate_async_script('navigator.clipboard.readText().then(arguments[0])')
-
- expect(copied_text).to eq(scrape_personal_key)
-
- click_continue
- mod = mac? ? :meta : :control
- page.find(':focus').send_keys [mod, 'v']
-
- path_before_submit = current_path
- within('[role=dialog]') { click_on t('forms.buttons.continue') }
- expect(current_path).not_to eq path_before_submit
- end
-
- it 'validates as case-insensitive, crockford-normalized, length-limited, dash-flexible' do
- code_segments = scrape_personal_key.split('-')
-
- click_acknowledge_personal_key
- input = page.find(':focus')
-
- # Validate as incorrect
- input.fill_in with: 'wrong!'
- within('[role=dialog]') { click_on t('forms.buttons.continue') }
- expect(page).to have_content(t('users.personal_key.confirmation_error'))
-
- # Validate as correct, with formatting variations...
-
- # Include dash between some segments and not others
- code = code_segments[0..1].join('-') + code_segments[2..3].join
-
- # Randomize case
- code = code.chars.map { |c| (rand 2) == 0 ? c.downcase : c.upcase }.join
-
- # De-normalize Crockford encoding
- code = code.sub('1', 'l').sub('0', 'O')
-
- # Add extra characters
- code += 'abc123qwerty'
-
- input.fill_in with: code
-
- within('[role=dialog]') { click_on t('forms.buttons.continue') }
- if address_verification_mechanism == :gpo
- expect(current_path).to eq idv_come_back_later_path
- else
- expect(current_path).to eq account_path
- end
- end
- end
-
- def mac?
- RbConfig::CONFIG['host_os'].match? 'darwin'
- end
-end
diff --git a/spec/views/shared/_personal_key.html.erb_spec.rb b/spec/views/shared/_personal_key.html.erb_spec.rb
index 594c9060d64..1d23828ceb4 100644
--- a/spec/views/shared/_personal_key.html.erb_spec.rb
+++ b/spec/views/shared/_personal_key.html.erb_spec.rb
@@ -29,29 +29,4 @@ def self.decode(value)
expect(data_uri.data).to eq(personal_key)
end
end
-
- describe 'continue button' do
- let(:idv_personal_key_confirmation_enabled) { nil }
-
- before do
- allow(FeatureManagement).to receive(:idv_personal_key_confirmation_enabled?).
- and_return(idv_personal_key_confirmation_enabled)
- end
-
- context 'without idv personal key confirmation' do
- let(:idv_personal_key_confirmation_enabled) { false }
-
- it 'renders button with [data-toggle="skip"]' do
- expect(rendered).to have_css('[data-toggle="skip"]')
- end
- end
-
- context 'with idv personal key confirmation' do
- let(:idv_personal_key_confirmation_enabled) { true }
-
- it 'renders button with [data-toggle="modal"]' do
- expect(rendered).to have_css('[data-toggle="modal"]')
- end
- end
- end
end