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:

  1. Change your password. Choose a password + that you haven't already used with this account.
  2. 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.
  3. 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:
    1. Change your password. Choose a password that you haven't already used with this account.
    2. 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.
    3. 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:

    1. Cambia + tu contraseña. Elige una contraseña que aún no hayas utilizado + con esta cuenta.
    2. 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.
    3. 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 :

    1. Modifiez votre mot de passe. Choisissez + un mot de passe que vous n'avez pas encore utilisé avec ce compte.
    2. 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é.
    3. 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.