From 15cb97344ba049a689b94a7f887c9b453784b58c Mon Sep 17 00:00:00 2001
From: Jonathan Hooper
Date: Thu, 15 Nov 2018 14:36:16 -0600
Subject: [PATCH 1/5] LG-785 Alert users when personal key is regenerated
**Why**: So that user's can be aware of any potential suspicious
activity associated with their account.
---
.../users/personal_keys_controller.rb | 10 +++++++
..._personal_key_regeneration_notifier_job.rb | 14 +++++++++
app/mailers/user_mailer.rb | 4 +++
.../personal_key_regenerated.html.slim | 16 ++++++++++
config/locales/jobs/en.yml | 7 +++--
config/locales/user_mailer/en.yml | 26 +++++++++++++---
.../users/regenerate_personal_key_spec.rb | 17 +++++++++--
...onal_key_regeneration_notifier_job_spec.rb | 30 +++++++++++++++++++
spec/mailers/user_mailer_spec.rb | 20 +++++++++++++
9 files changed, 136 insertions(+), 8 deletions(-)
create mode 100644 app/jobs/sms_personal_key_regeneration_notifier_job.rb
create mode 100644 app/views/user_mailer/personal_key_regenerated.html.slim
create mode 100644 spec/jobs/sms_personal_key_regeneration_notifier_job_spec.rb
diff --git a/app/controllers/users/personal_keys_controller.rb b/app/controllers/users/personal_keys_controller.rb
index 72f2b13d462..4dfccebce70 100644
--- a/app/controllers/users/personal_keys_controller.rb
+++ b/app/controllers/users/personal_keys_controller.rb
@@ -27,6 +27,7 @@ def create
user_session[:personal_key] = create_new_code
analytics.track_event(Analytics::PROFILE_PERSONAL_KEY_CREATE)
Event.create(user_id: current_user.id, event_type: :new_personal_key)
+ send_new_personal_key_notification
redirect_to manage_personal_key_url
end
@@ -45,5 +46,14 @@ def next_step
def user_has_not_visited_any_sp_yet?
current_user.identities.pluck(:last_authenticated_at).compact.empty?
end
+
+ def send_new_personal_key_notification
+ current_user.confirmed_email_addresses.each do |email_address|
+ UserMailer.personal_key_regenerated(email_address.email).deliver_now
+ end
+ MfaContext.new(current_user).phone_configurations.each do |phone_configuration|
+ SmsPersonalKeyRegenerationNotifierJob.perform_now(phone: phone_configuration.phone)
+ end
+ end
end
end
diff --git a/app/jobs/sms_personal_key_regeneration_notifier_job.rb b/app/jobs/sms_personal_key_regeneration_notifier_job.rb
new file mode 100644
index 00000000000..3ac8db56757
--- /dev/null
+++ b/app/jobs/sms_personal_key_regeneration_notifier_job.rb
@@ -0,0 +1,14 @@
+class SmsPersonalKeyRegenerationNotifierJob < ApplicationJob
+ queue_as :sms
+
+ # :reek:UtilityFunction
+ def perform(phone:)
+ TwilioService::Utils.new.send_sms(
+ to: phone,
+ body: I18n.t(
+ 'jobs.sms_personal_key_regeneration_notifier_job.message',
+ app: APP_NAME
+ )
+ )
+ end
+end
diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb
index dcf0044e6a0..f6461808faa 100644
--- a/app/mailers/user_mailer.rb
+++ b/app/mailers/user_mailer.rb
@@ -31,6 +31,10 @@ def personal_key_sign_in(email)
mail(to: email, subject: t('user_mailer.personal_key_sign_in.subject'))
end
+ def personal_key_regenerated(email)
+ mail(to: email, subject: t('user_mailer.personal_key_regenerated.subject'))
+ end
+
def account_reset_request(email_address, account_reset)
@token = account_reset&.request_token
mail(to: email_address.email, subject: t('user_mailer.account_reset_request.subject'))
diff --git a/app/views/user_mailer/personal_key_regenerated.html.slim b/app/views/user_mailer/personal_key_regenerated.html.slim
new file mode 100644
index 00000000000..9ae7e2becc0
--- /dev/null
+++ b/app/views/user_mailer/personal_key_regenerated.html.slim
@@ -0,0 +1,16 @@
+p.lead
+ strong == t('.intro')
+
+table.spacer
+ tbody
+ tr
+ td.s10 height="10px"
+ |
+table.hr
+ tr
+ th
+ |
+
+p == t('.help_html',
+ reset_password_url: forgot_password_url,
+ account_url: account_url)
diff --git a/config/locales/jobs/en.yml b/config/locales/jobs/en.yml
index 864b89c864a..f74ba0a79ba 100644
--- a/config/locales/jobs/en.yml
+++ b/config/locales/jobs/en.yml
@@ -12,6 +12,9 @@ en:
in to your account. This code will expire in %{expiration} minutes."
verify_message: "%{code} is your %{app} confirmation code. Use this to confirm
your phone number. This code will expire in %{expiration} minutes."
+ sms_personal_key_regeneration_notifier_job:
+ message: A new personal key has been issued for your %{app} account. If this
+ wasn’t you, reset your password and contact us at security@login.gov.
sms_personal_key_sign_in_notifier_job:
- message: Your personal key was just used to sign into your login.gov account.
- If this wasn’t you, reset your password and contact us at security@login.gov.
+ message: Your personal key was just used to sign into your %{app} account. If
+ this wasn’t you, reset your password and contact us at security@login.gov.
diff --git a/config/locales/user_mailer/en.yml b/config/locales/user_mailer/en.yml
index aaf2a4491e0..09c990c1001 100644
--- a/config/locales/user_mailer/en.yml
+++ b/config/locales/user_mailer/en.yml
@@ -44,6 +44,24 @@ en:
help: If you did not make this change, please visit the %{app} %{help_link}
or %{contact_link}.
intro: You have a new password for your %{app} account.
+ personal_key_regenerated:
+ help_html: Your login.gov account was just issued a new 16-character personal
+ key. You're getting this email to make sure it was you.
If you just
+ signed in and regenerated your personal key, great! There's nothing you need
+ to do.
If you did not just regenerate your personal key, or if you're
+ not sure, please immediately take these steps to secure your account:
- Change your password. Choose a password
+ that you haven't already used with this account.
- Sign
+ in to your login.gov account and make sure you recognize all of
+ the information on your account page, including the methods you use for two-factor
+ authentication, such as phone number, authentication app, or security key.
- On
+ your login.gov account page, request a new personal
+ key. Remember, never share it unless you are using it to sign into
+ a trusted website that uses login.gov.
You should then contact
+ us by calling 844-875-6446 or emailing security@login.gov.
Thanks,
The
+ login.gov team
+ intro: New personal key issued
+ subject: Account Security Alert
personal_key_sign_in:
help_html: Your login.gov account was just signed into using your 16-character
personal key. You're getting this email to make sure it was you.
If
@@ -55,10 +73,10 @@ en:
in to your login.gov account and make sure you recognize all
of the information on your account page, including the methods you use for
two-factor authentication, such as phone number, authentication app, or security
- key.
On your login.gov account page, request a new personal
- key. Remember, never share it unless you are using it to sign into
- a trusted website that uses login.gov.You should then contact
- us by calling 844-875-6446 or emailing security@login.gov.
+ key.On your login.gov account page,
+ request a new personal key. Remember, never share it unless you are
+ using it to sign into a trusted website that uses login.gov.You
+ should then contact us by calling 844-875-6446 or emailing security@login.gov.
Thanks,
The login.gov team
intro: Personal key used to sign in
subject: Account Security Alert
diff --git a/spec/features/users/regenerate_personal_key_spec.rb b/spec/features/users/regenerate_personal_key_spec.rb
index 88f9887669c..6b5677d4496 100644
--- a/spec/features/users/regenerate_personal_key_spec.rb
+++ b/spec/features/users/regenerate_personal_key_spec.rb
@@ -6,11 +6,15 @@
include SamlAuthHelper
context 'during sign up' do
- scenario 'user refreshes personal key page' do
+ scenario 'refreshing personal key page displays the same key and does not notify the user' do
sign_up_and_view_personal_key
personal_key = scrape_personal_key
+ # The user should not receive an SMS and an email
+ expect(UserMailer).to_not receive(:personal_key_regenerated)
+ expect(SmsPersonalKeyRegenerationNotifierJob).to_not receive(:perform_now)
+
visit sign_up_personal_key_path
expect(current_path).to eq(sign_up_personal_key_path)
@@ -24,10 +28,19 @@
context 'after sign up' do
context 'regenerating personal key' do
- scenario 'displays new code' do
+ scenario 'displays new code and notifies the user' do
user = sign_in_and_2fa_user
old_digest = user.encrypted_recovery_code_digest
+ # The user should receive an SMS and an email
+ personal_key_sign_in_mail = double
+ expect(personal_key_sign_in_mail).to receive(:deliver_now)
+ expect(UserMailer).to receive(:personal_key_regenerated).
+ with(user.email).
+ and_return(personal_key_sign_in_mail)
+ expect(SmsPersonalKeyRegenerationNotifierJob).to receive(:perform_now).
+ with(phone: user.phone_configurations.first.phone)
+
click_button t('account.links.regenerate_personal_key')
expect(user.reload.encrypted_recovery_code_digest).to_not eq old_digest
diff --git a/spec/jobs/sms_personal_key_regeneration_notifier_job_spec.rb b/spec/jobs/sms_personal_key_regeneration_notifier_job_spec.rb
new file mode 100644
index 00000000000..68a1763527b
--- /dev/null
+++ b/spec/jobs/sms_personal_key_regeneration_notifier_job_spec.rb
@@ -0,0 +1,30 @@
+require 'rails_helper'
+
+describe SmsPersonalKeyRegenerationNotifierJob do
+ include Features::ActiveJobHelper
+
+ before do
+ reset_job_queues
+ TwilioService::Utils.telephony_service = FakeSms
+ FakeSms.messages = []
+ end
+
+ describe '.perform' do
+ it 'sends a message about the personal key sign in to the user' do
+ allow(Figaro.env).to receive(:twilio_messaging_service_sid).and_return('fake_sid')
+
+ described_class.perform_now(phone: '+1 (202) 345-6789')
+
+ messages = FakeSms.messages
+
+ expect(messages.size).to eq(1)
+
+ msg = messages.first
+
+ expect(msg.messaging_service_sid).to eq('fake_sid')
+ expect(msg.to).to eq('+1 (202) 345-6789')
+ expect(msg.body).
+ to eq(I18n.t('jobs.sms_personal_key_regeneration_notifier_job.message', app: APP_NAME))
+ end
+ end
+end
diff --git a/spec/mailers/user_mailer_spec.rb b/spec/mailers/user_mailer_spec.rb
index 2ca18021e43..91a91a4fb4d 100644
--- a/spec/mailers/user_mailer_spec.rb
+++ b/spec/mailers/user_mailer_spec.rb
@@ -66,6 +66,26 @@
end
end
+ describe 'personal_key_regenerated' do
+ let(:mail) { UserMailer.personal_key_regenerated(user.email) }
+
+ it_behaves_like 'a system email'
+
+ it 'sends to the current email' do
+ expect(mail.to).to eq [user.email]
+ end
+
+ it 'renders the subject' do
+ expect(mail.subject).to eq t('user_mailer.personal_key_regenerated.subject')
+ end
+
+ it 'renders the body' do
+ expect(mail.html_part.body).to have_content(
+ t('user_mailer.personal_key_regenerated.intro')
+ )
+ end
+ end
+
describe 'signup_with_your_email' do
let(:mail) { UserMailer.signup_with_your_email(user.email) }
From c90cd881624cc10cc907bc85e899874004e88fb6 Mon Sep 17 00:00:00 2001
From: Jonathan Hooper
Date: Thu, 15 Nov 2018 15:02:05 -0600
Subject: [PATCH 2/5] normalize yaml
---
config/locales/user_mailer/en.yml | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/config/locales/user_mailer/en.yml b/config/locales/user_mailer/en.yml
index 09c990c1001..55f0e59a478 100644
--- a/config/locales/user_mailer/en.yml
+++ b/config/locales/user_mailer/en.yml
@@ -52,13 +52,13 @@ en:
not sure, please immediately take these steps to secure your account:- Change your password. Choose a password
that you haven't already used with this account.
- Sign
- in to your login.gov account and make sure you recognize all of
- the information on your account page, including the methods you use for two-factor
- authentication, such as phone number, authentication app, or security key.
- On
- your login.gov account page, request a new personal
- key. Remember, never share it unless you are using it to sign into
- a trusted website that uses login.gov.
You should then contact
- us by calling 844-875-6446 or emailing security@login.gov.
Thanks,
The
+ in to your login.gov account and make sure you recognize all
+ of the information on your account page, including the methods you use for
+ two-factor authentication, such as phone number, authentication app, or security
+ key.On your login.gov account page,
+ request a new personal key. Remember, never share it unless you are
+ using it to sign into a trusted website that uses login.gov.You
+ should then contact us by calling 844-875-6446 or emailing security@login.gov.
Thanks,
The
login.gov team
intro: New personal key issued
subject: Account Security Alert
From d946efd400c9c1265c0cc0ff450f5f0b2ef00167 Mon Sep 17 00:00:00 2001
From: Jonathan Hooper
Date: Thu, 15 Nov 2018 15:16:38 -0600
Subject: [PATCH 3/5] fix a spec
---
spec/features/users/regenerate_personal_key_spec.rb | 2 ++
1 file changed, 2 insertions(+)
diff --git a/spec/features/users/regenerate_personal_key_spec.rb b/spec/features/users/regenerate_personal_key_spec.rb
index 6b5677d4496..1bceac55cd6 100644
--- a/spec/features/users/regenerate_personal_key_spec.rb
+++ b/spec/features/users/regenerate_personal_key_spec.rb
@@ -5,6 +5,8 @@
include PersonalKeyHelper
include SamlAuthHelper
+ before { stub_twilio_service }
+
context 'during sign up' do
scenario 'refreshing personal key page displays the same key and does not notify the user' do
sign_up_and_view_personal_key
From ceff5b80bf51f1bd6ea4011121975f6c71990acb Mon Sep 17 00:00:00 2001
From: Jonathan Hooper
Date: Fri, 16 Nov 2018 09:55:20 -0600
Subject: [PATCH 4/5] Add translations
---
config/locales/jobs/es.yml | 3 +++
config/locales/jobs/fr.yml | 4 ++++
config/locales/user_mailer/es.yml | 21 +++++++++++++++++++++
config/locales/user_mailer/fr.yml | 21 +++++++++++++++++++++
4 files changed, 49 insertions(+)
diff --git a/config/locales/jobs/es.yml b/config/locales/jobs/es.yml
index d2aec114d8d..71d68faf1ed 100644
--- a/config/locales/jobs/es.yml
+++ b/config/locales/jobs/es.yml
@@ -12,6 +12,9 @@ es:
ingresando a su cuenta. Este código caducará en %{expiration} minutos."
verify_message: "%{code} es tu código de confirmación de %{app}. Use esto para
confirmar su número de teléfono. Este código caducará en %{expiration} minutos."
+ sms_personal_key_regeneration_notifier_job:
+ message: Se ha emitido una nueva clave personal para tu cuenta %{app}. Si no
+ eres tú, restablece tu contraseña y ponte en contacto con nosotros en security@login.gov.
sms_personal_key_sign_in_notifier_job:
message: Su clave personal solo se utilizó para iniciar sesión en su cuenta
login.gov. Si no fue así, reinicie su contraseña y contáctenos en security@login.gov.
diff --git a/config/locales/jobs/fr.yml b/config/locales/jobs/fr.yml
index a2aa952d6ab..98ed9aa956a 100644
--- a/config/locales/jobs/fr.yml
+++ b/config/locales/jobs/fr.yml
@@ -14,6 +14,10 @@ fr:
verify_message: "%{code} est votre code de confirmation %{app}. Utilisez-le
pour confirmer votre numéro de téléphone. Ce code expirera dans %{expiration}
minutes."
+ sms_personal_key_regeneration_notifier_job:
+ message: Une nouvelle clé personnelle a été émise pour votre compte %{app}.
+ Si vous ne l'avez pas demandée, réinitialisez votre mot de passe et contactez-nous
+ à security@login.gov.
sms_personal_key_sign_in_notifier_job:
message: Votre clé personnelle a été utilisée pour vous connecter à votre compte
login.gov. Si ce n’était pas vous, changez votre mot de passe et contactez-nous
diff --git a/config/locales/user_mailer/es.yml b/config/locales/user_mailer/es.yml
index eb4eb6a58dc..5cc4f6ba901 100644
--- a/config/locales/user_mailer/es.yml
+++ b/config/locales/user_mailer/es.yml
@@ -43,6 +43,27 @@ es:
password_changed:
help: Si no realizó este cambio, visite el %{app} %{help_link} o el %{contact_link}.
intro: Tiene una contraseña nueva para su cuenta de %{app}.
+ personal_key_regenerated:
+ help_html: Tu cuenta de login.gov acaba de emitir una nueva clave personal
+ de 16 caracteres. Estás recibiendo este correo electrónico para verificar
+ que eras tú.
Si acabas de iniciar sesión y has regenerado tu clave
+ personal, ¡fantástico! No es necesario que hagas nada.
Si no acabas
+ de regenerar tu clave personal, o si no estás seguro, sigue estos pasos para
+ proteger tu cuenta:
- Cambia
+ tu contraseña. Elige una contraseña que aún no hayas utilizado
+ con esta cuenta.
- Inicia sesión en
+ tu cuenta de login.gov y asegúrate de que reconoces toda la información
+ de la página de tu cuenta, como los métodos que utilizas para la autenticación
+ de dos factores, como el número de teléfono, la aplicación de autenticación
+ o la clave de seguridad.
- En la página
+ de tu cuenta de login.gov, solicita una nueva clave personal.
+ Recuerda no compartirla nunca a menos que la estés usando para acceder a un
+ sitio web de confianza que utilice login.gov.
Deberías ponerte
+ en contacto con nosotros llamando al 844-875-6446 o enviando un correo electrónico
+ a security@login.gov.
Gracias,
El
+ equipo de login.gov
+ intro: Nueva clave personal emitida
+ subject: Alerta de seguridad de la cuenta
personal_key_sign_in:
help_html: Su cuenta login.gov acaba de iniciar sesión con su clave personal
de 16 caracteres. Usted está recibiendo este e-mail para asegurarse de que
diff --git a/config/locales/user_mailer/fr.yml b/config/locales/user_mailer/fr.yml
index 1c386e50dba..5e6e73b709c 100644
--- a/config/locales/user_mailer/fr.yml
+++ b/config/locales/user_mailer/fr.yml
@@ -45,6 +45,27 @@ fr:
help: Si vous n'avez pas changé votre mot de passe, veuillez visiter le %{help_link}
de %{app} ou %{contact_link}.
intro: Le mot de passe de votre compte %{app} a été changé.
+ personal_key_regenerated:
+ help_html:
Votre compte login.gov vient de recevoir une nouvelle clé personnelle
+ de 16 caractères. Le but de cet e-mail est de s'assurer que c'est bien vous
+ qui en êtes à l'origine.
Si vous venez de vous connecter et de régénérer
+ votre clé personnelle, c'est parfait ! Vous n'avez rien à faire.
Si
+ vous ne venez pas de régénérer votre clé personnelle, ou en cas de doute,
+ effectuez immédiatement les actions suivantes pour sécuriser votre compte :
- Modifiez votre mot de passe. Choisissez
+ un mot de passe que vous n'avez pas encore utilisé avec ce compte.
- Connectez-vous à votre compte login.gov
+ et vérifiez bien que toutes les informations sur la page de votre compte sont
+ correctes, y compris les méthodes que vous utilisez pour l’authentification
+ à deux facteurs, dont le numéro de téléphone, l’application d’authentification
+ ou la clé de sécurité.
- Sur votre page
+ de compte login.gov, demandez une nouvelle clé personnelle. N'oubliez
+ pas de ne jamais la partager, sauf si vous l'utilisez pour vous connecter
+ à un site de confiance qui utilise login.gov.
Veuillez ensuite
+ nous contacter en appelant le 844-875-6446 ou par e-mail à security@login.gov.
Merci,
L'équipe
+ login.gov
+ intro: Nouvelle clé personnelle émise
+ subject: Alerte de sécurité du compte
personal_key_sign_in:
help_html: Votre compte login.gov a été connecté à l'aide de votre clé personnelle.
Vous recevez cet email pour vous assurer que c'était bien vous.
Si vous
From f97ace664cdd33c3cb2739905529d91103482168 Mon Sep 17 00:00:00 2001
From: Jonathan Hooper
Date: Fri, 16 Nov 2018 10:04:46 -0600
Subject: [PATCH 5/5] Fix a i18n test
---
config/locales/jobs/es.yml | 2 +-
config/locales/jobs/fr.yml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/config/locales/jobs/es.yml b/config/locales/jobs/es.yml
index 71d68faf1ed..8d29586838d 100644
--- a/config/locales/jobs/es.yml
+++ b/config/locales/jobs/es.yml
@@ -17,4 +17,4 @@ es:
eres tú, restablece tu contraseña y ponte en contacto con nosotros en security@login.gov.
sms_personal_key_sign_in_notifier_job:
message: Su clave personal solo se utilizó para iniciar sesión en su cuenta
- login.gov. Si no fue así, reinicie su contraseña y contáctenos en security@login.gov.
+ %{app}. Si no fue así, reinicie su contraseña y contáctenos en security@login.gov.
diff --git a/config/locales/jobs/fr.yml b/config/locales/jobs/fr.yml
index 98ed9aa956a..f4302b8bc74 100644
--- a/config/locales/jobs/fr.yml
+++ b/config/locales/jobs/fr.yml
@@ -20,5 +20,5 @@ fr:
à security@login.gov.
sms_personal_key_sign_in_notifier_job:
message: Votre clé personnelle a été utilisée pour vous connecter à votre compte
- login.gov. Si ce n’était pas vous, changez votre mot de passe et contactez-nous
+ %{app}. Si ce n’était pas vous, changez votre mot de passe et contactez-nous
à security@login.gov.