Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LG-15059: Socure timeout page #11572

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
Open
70 changes: 43 additions & 27 deletions app/controllers/idv/document_capture_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ class DocumentCaptureController < ApplicationController
include IdvStepConcern
include StepIndicatorConcern

before_action :confirm_not_rate_limited, except: [:update]
before_action :confirm_not_rate_limited, except: [:update, :direct_in_person]
before_action :confirm_step_allowed, unless: -> { allow_direct_ipp? }
before_action :override_csp_to_allow_acuant
before_action :set_usps_form_presenter
before_action -> { redirect_to_correct_vendor(Idp::Constants::Vendors::LEXIS_NEXIS, false) },
only: :show
only: [:show], unless: -> { allow_direct_ipp? }

def show
analytics.idv_doc_auth_document_capture_visited(**analytics_arguments)
Expand Down Expand Up @@ -43,20 +43,15 @@ def update
end
end

def extra_view_variables
{
document_capture_session_uuid: document_capture_session_uuid,
mock_client: doc_auth_vendor == 'mock',
flow_path: 'standard',
sp_name: decorated_sp_session.sp_name,
failure_to_proof_url: return_to_sp_failure_to_proof_url(step: 'document_capture'),
skip_doc_auth_from_how_to_verify: idv_session.skip_doc_auth_from_how_to_verify,
skip_doc_auth_from_handoff: idv_session.skip_doc_auth_from_handoff,
opted_in_to_in_person_proofing: idv_session.opted_in_to_in_person_proofing,
doc_auth_selfie_capture: resolved_authn_context_result.facial_match?,
}.merge(
acuant_sdk_upgrade_a_b_testing_variables,
)
# Given that the start of the IPP flow is in the TrueID doc_auth React app,
# we need a generic, direct way to start the IPP flow
def direct_in_person
attributes = {
remaining_submit_attempts: rate_limiter.remaining_count,
}.merge(ab_test_analytics_buckets)
analytics.idv_in_person_direct_start(**attributes)

redirect_to idv_document_capture_url(step: :idv_doc_auth)
end

def self.step_info
Expand All @@ -65,15 +60,15 @@ def self.step_info
controller: self,
next_steps: [:ssn, :ipp_ssn], # :ipp_state_id
preconditions: ->(idv_session:, user:) {
idv_session.flow_path == 'standard' && (
# mobile
idv_session.skip_doc_auth_from_handoff ||
idv_session.skip_hybrid_handoff ||
idv_session.skip_doc_auth_from_how_to_verify ||
!idv_session.selfie_check_required || # desktop but selfie not required
idv_session.desktop_selfie_test_mode_enabled?
)
},
idv_session.flow_path == 'standard' && (
# mobile
idv_session.skip_doc_auth_from_handoff ||
idv_session.skip_hybrid_handoff ||
idv_session.skip_doc_auth_from_how_to_verify ||
!idv_session.selfie_check_required || # desktop but selfie not required
idv_session.desktop_selfie_test_mode_enabled?
)
},
undo_step: ->(idv_session:, user:) do
idv_session.pii_from_doc = nil
idv_session.invalidate_in_person_pii_from_user!
Expand All @@ -86,6 +81,22 @@ def self.step_info

private

def extra_view_variables
{
document_capture_session_uuid: document_capture_session_uuid,
mock_client: doc_auth_vendor == 'mock',
flow_path: 'standard',
sp_name: decorated_sp_session.sp_name,
failure_to_proof_url: return_to_sp_failure_to_proof_url(step: 'document_capture'),
skip_doc_auth_from_how_to_verify: idv_session.skip_doc_auth_from_how_to_verify,
skip_doc_auth_from_handoff: idv_session.skip_doc_auth_from_handoff,
opted_in_to_in_person_proofing: idv_session.opted_in_to_in_person_proofing,
doc_auth_selfie_capture: resolved_authn_context_result.facial_match?,
}.merge(
acuant_sdk_upgrade_a_b_testing_variables,
)
end

def analytics_arguments
{
flow_path: flow_path,
Expand All @@ -102,8 +113,9 @@ def allow_direct_ipp?
return false unless idv_session.welcome_visited &&
idv_session.idv_consent_given?
# not allowed when no step param and action:show(get request)
return false if params[:step].blank? || params[:action].to_s != 'show' ||
idv_session.flow_path == 'hybrid'
return false if params[:step].blank?
return false if params[:action].to_s != 'show' && params[:action] != 'direct_in_person'
return false if idv_session.flow_path == 'hybrid'
# Only allow direct access to document capture if IPP available
return false unless IdentityConfig.store.in_person_doc_auth_button_enabled &&
Idv::InPersonConfig.enabled_for_issuer?(decorated_sp_session.sp_issuer)
Expand All @@ -118,5 +130,9 @@ def allow_direct_ipp?
def set_usps_form_presenter
@presenter = Idv::InPerson::UspsFormPresenter.new
end

def rate_limiter
RateLimiter.new(user: idv_session.current_user, rate_limit_type: :idv_doc_auth)
end
end
end
4 changes: 1 addition & 3 deletions app/controllers/idv/socure/document_capture_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,7 @@ def wait_for_result?
# If the stored_result is nil, the job fetching the results has not completed.
analytics.idv_doc_auth_document_capture_polling_wait_visited(**analytics_arguments)
if wait_timed_out?
# flash[:error] = I18n.t('errors.doc_auth.polling_timeout')
# TODO: redirect to try again page LG-14873/14952/15059
render plain: 'Technical difficulties!!!', status: :ok
redirect_to idv_socure_errors_timeout_path
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍🏿
do we also need this behavior for the hybrid socure flow? 🤔

else
@refresh_interval =
IdentityConfig.store.doc_auth_socure_wait_polling_refresh_max_seconds
Expand Down
58 changes: 58 additions & 0 deletions app/controllers/idv/socure/errors_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# frozen_string_literal: true

module Idv
module Socure
class ErrorsController < ApplicationController
include Idv::AvailabilityConcern
include IdvStepConcern
include StepIndicatorConcern
include Idv::AbTestAnalyticsConcern

before_action :confirm_step_allowed
before_action :set_in_person_available

def timeout
@remaining_submit_attempts = rate_limiter.remaining_count
track_event(type: :timeout)
end

def self.step_info
Idv::StepInfo.new(
key: :socure_errors,
controller: self,
action: :timeout,
next_steps: [FlowPolicy::FINAL],
preconditions: ->(idv_session:, user:) do
idv_session.socure_docv_wait_polling_started_at.present?
end,
undo_step: ->(idv_session:, user:) {},
)
end

private

def rate_limiter
RateLimiter.new(user: idv_session.current_user, rate_limit_type: :idv_doc_auth)
end

def track_event(type:)
attributes = { type: type }.merge(ab_test_analytics_buckets)
if type == :timeout
attributes[:remaining_submit_attempts] = @remaining_submit_attempts
end

analytics.idv_doc_auth_socure_error_visited(**attributes)
end

def set_in_person_available
@idv_in_person_url = in_person_enabled? ?
idv_in_person_direct_path(step: :socure_doc_auth) : nil
end

def in_person_enabled?
IdentityConfig.store.in_person_doc_auth_button_enabled &&
Idv::InPersonConfig.enabled_for_issuer?(document_capture_session&.issuer)
end
end
end
end
1 change: 1 addition & 0 deletions app/policies/idv/flow_policy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ def steps
link_sent: Idv::LinkSentController.step_info,
document_capture: Idv::DocumentCaptureController.step_info,
socure_document_capture: Idv::Socure::DocumentCaptureController.step_info,
socure_errors: Idv::Socure::ErrorsController.step_info,
ipp_address: Idv::InPerson::AddressController.step_info,
ssn: Idv::SsnController.step_info,
ipp_ssn: Idv::InPerson::SsnController.step_info,
Expand Down
41 changes: 41 additions & 0 deletions app/services/analytics_events.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1698,6 +1698,28 @@ def idv_doc_auth_redo_ssn_submitted(
)
end

# User is shown the Socure timeout error page
# @param [String] type The type of error that occurred
# @param [Integer] remaining_submit_attempts The number of remaining attempts to submit
# @param [Boolean] skip_hybrid_handoff Whether the user skipped the hybrid handoff A/B test
# @param [Boolean] opted_in_to_in_person_proofing Whether the user opted into in-person proofing
def idv_doc_auth_socure_error_visited(
type:,
remaining_submit_attempts:,
skip_hybrid_handoff: nil,
opted_in_to_in_person_proofing: nil,
**extra
)
track_event(
:idv_doc_auth_socure_error_visited,
type:,
remaining_submit_attempts:,
skip_hybrid_handoff:,
opted_in_to_in_person_proofing:,
**extra,
)
end

# @param [String] created_at The created timestamp received from Socure
# @param [String] customer_user_id The customerUserId received from Socure
# @param [String] docv_transaction_token The docvTransactionToken received from Socure
Expand Down Expand Up @@ -2789,6 +2811,25 @@ def idv_image_capture_failed(
end
# rubocop:enable Naming/VariableName,Naming/MethodParameterName

# User chooses to try In Person, e.g. from a doc_auth timeout error page
# @param [Integer] remaining_submit_attempts The number of remaining attempts to submit
# @param [Boolean] skip_hybrid_handoff Whether the user skipped the hybrid handoff A/B test
# @param [Boolean] opted_in_to_in_person_proofing Whether the user opted into in-person proofing
def idv_in_person_direct_start(
remaining_submit_attempts:,
skip_hybrid_handoff: nil,
opted_in_to_in_person_proofing: nil,
**extra
)
track_event(
:idv_in_person_direct_start,
remaining_submit_attempts:,
skip_hybrid_handoff:,
opted_in_to_in_person_proofing:,
**extra,
)
end

# Tracks emails that are initiated during InPerson::EmailReminderJob
# @param [String] email_type early or late
# @param [String] enrollment_id
Expand Down
2 changes: 1 addition & 1 deletion app/views/idv/phone_errors/warning.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
</p>

<p>
<%= t('idv.failure.phone.warning.attempts_html', count: @remaining_submit_attempts) %>
<%= t('idv.failure.warning.attempts_html', count: @remaining_submit_attempts) %>
</p>

<div class="margin-y-5">
Expand Down
42 changes: 42 additions & 0 deletions app/views/idv/socure/errors/timeout.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<%= render(
'idv/shared/error',
type: :warning,
title: t('idv.errors.technical_difficulties'),
heading: t('idv.errors.technical_difficulties'),
current_step: :verify_id,
) do %>
<p>
<%= t('idv.errors.try_again_later') %>
</p>
<p>
<%= t('idv.failure.warning.attempts_html', count: @remaining_submit_attempts) %>
</p>

<div class="margin-y-5">
<%= render ButtonComponent.new(
url: idv_socure_document_capture_path,
big: true,
wide: true,
).with_content(t('idv.failure.button.warning')) %>
</div>

<% if @idv_in_person_url %>
<hr>

<h2><%= t('in_person_proofing.headings.cta') %></h2>

<p>
<%= t('in_person_proofing.body.cta.prompt_detail') %>
</p>

<div class="margin-y-5">
<%= render ButtonComponent.new(
url: @idv_in_person_url,
big: true,
wide: true,
outline: true,
).with_content(t('in_person_proofing.body.cta.button')) %>
</div>
<% end %>
<% end %>
<%= render('idv/doc_auth/cancel', step: 'socure') %>
6 changes: 4 additions & 2 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1049,6 +1049,8 @@ idv.errors.incorrect_password: The password you entered is not correct.
idv.errors.pattern_mismatch.ssn: Enter a nine-digit Social Security number
idv.errors.pattern_mismatch.zipcode: Enter a 5 or 9 digit ZIP Code
idv.errors.pattern_mismatch.zipcode_five: Enter a 5 digit ZIP Code
idv.errors.technical_difficulties: We are having technical difficulties
idv.errors.try_again_later: Try again later.
idv.failure.attempts_html.one: You can try <strong>1 more time.</strong> Then, you must wait 6 hours before trying again.
idv.failure.attempts_html.other: You can try <strong>%{count} more times.</strong> Then, you must wait 6 hours before trying again.
idv.failure.button.try_online: Try again online
Expand All @@ -1075,8 +1077,6 @@ idv.failure.phone.rate_limited.option_try_again_later_no_gpo_html: You can try a
idv.failure.phone.rate_limited.option_verify_by_mail_html: Verify by mail, which takes <strong>5 to 10 days</strong>
idv.failure.phone.rate_limited.options_header: 'You can:'
idv.failure.phone.timeout: Our request to verify your information timed out. Please try again.
idv.failure.phone.warning.attempts_html.one: For security reasons, you have <strong>one attempt</strong> remaining.
idv.failure.phone.warning.attempts_html.other: For security reasons, you have <strong>%{count} attempts</strong> remaining.
idv.failure.phone.warning.gpo.button: Verify by mail
idv.failure.phone.warning.gpo.explanation: If you don’t have another phone number to try, verify by mail instead.
idv.failure.phone.warning.gpo.heading: Verify by mail
Expand All @@ -1098,6 +1098,8 @@ idv.failure.verify.exit: Exit %{app_name}
idv.failure.verify.fail_link_html: Get help at <strong>%{sp_name}</strong>
idv.failure.verify.fail_text: to access services.
idv.failure.verify.heading: We couldn’t verify your identity
idv.failure.warning.attempts_html.one: For security reasons, you have <strong>one attempt</strong> remaining.
idv.failure.warning.attempts_html.other: For security reasons, you have <strong>%{count} attempts</strong> remaining.
idv.forgot_password.link_text: Forgot password?
idv.forgot_password.modal_header: Are you sure you can’t remember your password?
idv.forgot_password.reset_password: Reset password
Expand Down
6 changes: 4 additions & 2 deletions config/locales/es.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1060,6 +1060,8 @@ idv.errors.incorrect_password: La contraseña que ingresó no es la correcta.
idv.errors.pattern_mismatch.ssn: Ingrese un número de Seguro Social de nueve dígitos.
idv.errors.pattern_mismatch.zipcode: Ingrese un código postal de 5 o 9 dígitos.
idv.errors.pattern_mismatch.zipcode_five: Ingrese un código postal de 5 dígitos.
idv.errors.technical_difficulties: Estamos teniendo problemas técnicos
idv.errors.try_again_later: Vuelva a intentarlo más tarde.
idv.failure.attempts_html.one: Puede intentarlo <strong>una vez más.</strong> Luego, debe esperar 6 horas antes de volver a intentarlo.
idv.failure.attempts_html.other: Puede intentarlo <strong>%{count} veces más.</strong> Luego, debe esperar 6 horas antes de volver a intentarlo.
idv.failure.button.try_online: Vuelva a intentarlo en línea
Expand All @@ -1086,8 +1088,6 @@ idv.failure.phone.rate_limited.option_try_again_later_no_gpo_html: Puede volver
idv.failure.phone.rate_limited.option_verify_by_mail_html: Verificar por correo, lo que tarda de <strong>5 a 10 días</strong>
idv.failure.phone.rate_limited.options_header: 'Usted puede:'
idv.failure.phone.timeout: Terminó el tiempo de nuestra solicitud para verificar su información. Vuelva a intentarlo.
idv.failure.phone.warning.attempts_html.one: Por motivos de seguridad, le queda <strong>un intento</strong>.
idv.failure.phone.warning.attempts_html.other: Por motivos de seguridad, le quedan <strong>%{count} intentos</strong>.
idv.failure.phone.warning.gpo.button: Verificar por correo
idv.failure.phone.warning.gpo.explanation: Si no tiene otro número de teléfono para intentarlo, haga la verificación por correo.
idv.failure.phone.warning.gpo.heading: Verificar por correo
Expand All @@ -1109,6 +1109,8 @@ idv.failure.verify.exit: Salir de %{app_name}
idv.failure.verify.fail_link_html: Obtenga ayuda en <strong>%{sp_name}</strong>
idv.failure.verify.fail_text: para acceder a los servicios.
idv.failure.verify.heading: No pudimos verificar su identidad
idv.failure.warning.attempts_html.one: Por motivos de seguridad, le queda <strong>un intento</strong>.
idv.failure.warning.attempts_html.other: Por motivos de seguridad, le quedan <strong>%{count} intentos</strong>.
idv.forgot_password.link_text: '¿Olvidó su contraseña?'
idv.forgot_password.modal_header: '¿Está seguro de que no puede recordar su contraseña?'
idv.forgot_password.reset_password: Restablecer la contraseña
Expand Down
6 changes: 4 additions & 2 deletions config/locales/fr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1049,6 +1049,8 @@ idv.errors.incorrect_password: Le mot de passe que vous avez saisi est incorrect
idv.errors.pattern_mismatch.ssn: Saisissez un numéro de sécurité sociale à neuf chiffres
idv.errors.pattern_mismatch.zipcode: Saisissez un code postal à 5 ou 9 chiffres
idv.errors.pattern_mismatch.zipcode_five: Saisissez un code postal à 5 chiffres
idv.errors.technical_difficulties: Nous rencontrons des difficultés techniques
idv.errors.try_again_later: Veuillez réessayer ultérieurement.
idv.failure.attempts_html.one: Vous avez encore <strong>un essai.</strong> Vous devrez ensuite attendre 6 heures avant de réessayer.
idv.failure.attempts_html.other: Vous pouvez encore essayer <strong>%{count} fois de plus.</strong> Ensuite, vous devrez ensuite attendre 6 heures avant de réessayer.
idv.failure.button.try_online: Réessayer en ligne
Expand All @@ -1075,8 +1077,6 @@ idv.failure.phone.rate_limited.option_try_again_later_no_gpo_html: Vous pourrez
idv.failure.phone.rate_limited.option_verify_by_mail_html: Vérifier par courrier, ce qui prend <strong>5 à 10 jours</strong>.
idv.failure.phone.rate_limited.options_header: 'Vous pouvez :'
idv.failure.phone.timeout: Notre demande de vérification de vos renseignements a expiré. Veuillez réessayer.
idv.failure.phone.warning.attempts_html.one: Pour des raisons de sécurité, il vous reste <strong>une tentative</strong>.
idv.failure.phone.warning.attempts_html.other: Pour des raisons de sécurité, il vous reste <strong>%{count} tentatives</strong>.
idv.failure.phone.warning.gpo.button: Vérifier par courrier
idv.failure.phone.warning.gpo.explanation: Si vous n’avez pas d’autre numéro de téléphone à essayer, vérifiez plutôt par courrier.
idv.failure.phone.warning.gpo.heading: Vérifier par courrier
Expand All @@ -1098,6 +1098,8 @@ idv.failure.verify.exit: Quitter %{app_name}
idv.failure.verify.fail_link_html: Obtenez de l’aide auprès de <strong>%{sp_name}</strong>
idv.failure.verify.fail_text: pour accéder aux services.
idv.failure.verify.heading: Nous n’avons pas pu confirmer votre identité
idv.failure.warning.attempts_html.one: Pour des raisons de sécurité, il vous reste <strong>une tentative</strong>.
idv.failure.warning.attempts_html.other: Pour des raisons de sécurité, il vous reste <strong>%{count} tentatives</strong>.
idv.forgot_password.link_text: Mot de passe oublié?
idv.forgot_password.modal_header: Êtes-vous sûr de ne pas pouvoir vous souvenir de votre mot de passe?
idv.forgot_password.reset_password: Réinitialiser le mot de passe
Expand Down
Loading