From cd522e78783c65f775a5bd947e377b4012b87e1b Mon Sep 17 00:00:00 2001 From: Jack Cody Date: Tue, 23 Aug 2022 17:46:53 -0700 Subject: [PATCH 1/3] Add tracker event idv_phone_otp_submitted_rate_limited --- app/services/irs_attempts_api/tracker_events.rb | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/services/irs_attempts_api/tracker_events.rb b/app/services/irs_attempts_api/tracker_events.rb index e644ee1a3c4..7b8ce9adcdc 100644 --- a/app/services/irs_attempts_api/tracker_events.rb +++ b/app/services/irs_attempts_api/tracker_events.rb @@ -50,6 +50,15 @@ def forgot_password_email_confirmed(success:, failure_reason: nil) ) end + # The user reached the rate limit for Idv phone OTP submitted + # @param [String] phone + def idv_phone_otp_submitted_rate_limited(phone:) + track_event( + :idv_phone_otp_submitted_rate_limited, + phone: phone, + ) + end + # @param [Boolean] success True if the email and password matched # A user has initiated a logout event def logout_initiated(success:) From 991af6e0a81f678d82bb7fbe362770d97ee8b01f Mon Sep 17 00:00:00 2001 From: Jack Cody Date: Tue, 23 Aug 2022 17:47:55 -0700 Subject: [PATCH 2/3] Submit event when throttled --- app/controllers/idv/otp_verification_controller.rb | 1 + .../phone_confirmation_otp_verification_form.rb | 14 +++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/app/controllers/idv/otp_verification_controller.rb b/app/controllers/idv/otp_verification_controller.rb index b792ad544eb..9e7a0d12adb 100644 --- a/app/controllers/idv/otp_verification_controller.rb +++ b/app/controllers/idv/otp_verification_controller.rb @@ -61,6 +61,7 @@ def phone_confirmation_otp_verification_form @phone_confirmation_otp_verification_form ||= PhoneConfirmationOtpVerificationForm.new( user: current_user, user_phone_confirmation_session: idv_session.user_phone_confirmation_session, + irs_attempts_api_tracker: irs_attempts_api_tracker, ) end end diff --git a/app/forms/idv/phone_confirmation_otp_verification_form.rb b/app/forms/idv/phone_confirmation_otp_verification_form.rb index 19016f09e6f..6caa41867e7 100644 --- a/app/forms/idv/phone_confirmation_otp_verification_form.rb +++ b/app/forms/idv/phone_confirmation_otp_verification_form.rb @@ -1,10 +1,11 @@ module Idv class PhoneConfirmationOtpVerificationForm - attr_reader :user, :user_phone_confirmation_session, :code + attr_reader :user, :user_phone_confirmation_session, :irs_attempts_api_tracker, :code - def initialize(user:, user_phone_confirmation_session:) + def initialize(user:, user_phone_confirmation_session:, irs_attempts_api_tracker:) @user = user @user_phone_confirmation_session = user_phone_confirmation_session + @irs_attempts_api_tracker = irs_attempts_api_tracker end def submit(code:) @@ -32,11 +33,18 @@ def clear_second_factor_attempts def increment_second_factor_attempts user.second_factor_attempts_count += 1 attributes = {} - attributes[:second_factor_locked_at] = Time.zone.now if user.max_login_attempts? + if user.max_login_attempts? + attributes[:second_factor_locked_at] = Time.zone.now + irs_attempts_api_tracker.idv_phone_otp_submitted_rate_limited(phone: user_phone) + end UpdateUser.new(user: user, attributes: attributes).call end + def user_phone + user_phone_confirmation_session.phone + end + def extra_analytics_attributes { code_expired: user_phone_confirmation_session.expired?, From fe8f621eac17cd08c347f75381e38a3828e53b40 Mon Sep 17 00:00:00 2001 From: Jack Cody Date: Tue, 23 Aug 2022 17:48:09 -0700 Subject: [PATCH 3/3] Add spec changelog: Internal, Attempts API, Track additional events --- ...one_confirmation_otp_verification_form_spec.rb | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/spec/forms/idv/phone_confirmation_otp_verification_form_spec.rb b/spec/forms/idv/phone_confirmation_otp_verification_form_spec.rb index f20a3c5faeb..240741933b0 100644 --- a/spec/forms/idv/phone_confirmation_otp_verification_form_spec.rb +++ b/spec/forms/idv/phone_confirmation_otp_verification_form_spec.rb @@ -13,11 +13,19 @@ delivery_method: :sms, ) end + let(:irs_attempts_api_tracker) do + instance_double( + IrsAttemptsApi::Tracker, + idv_phone_otp_submitted_rate_limited: true, + ) + end describe '#submit' do def try_submit(code) described_class.new( - user: user, user_phone_confirmation_session: user_phone_confirmation_session, + user: user, + user_phone_confirmation_session: user_phone_confirmation_session, + irs_attempts_api_tracker: irs_attempts_api_tracker, ).submit(code: code) end @@ -64,6 +72,10 @@ def try_submit(code) context 'when the code is expired' do let(:phone_confirmation_otp_sent_at) { 11.minutes.ago } + before do + allow(IrsAttemptsApi::Tracker).to receive(:new).and_return(irs_attempts_api_tracker) + end + it 'returns an unsuccessful result' do result = try_submit(phone_confirmation_otp_code) @@ -84,6 +96,7 @@ def try_submit(code) expect(user.second_factor_attempts_count).to eq(3) expect(user.second_factor_locked_at).to be_within(1.second).of(Time.zone.now) + expect(irs_attempts_api_tracker).to have_received(:idv_phone_otp_submitted_rate_limited) end end