Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions app/controllers/concerns/idv/verify_info_concern.rb
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,27 @@ def ssn_rate_limiter

def idv_failure(result)
proofing_results_exception = result.extra.dig(:proofing_results, :exception)
has_exception = proofing_results_exception.present?
is_mva_exception = result.extra.dig(
:proofing_results,
:context,
:stages,
:state_id,
:mva_exception,
).present?
is_threatmetrix_exception = result.extra.dig(
:proofing_results,
:context,
:stages,
:threatmetrix,
:exception,
).present?
resolution_failed = !result.extra.dig(
:proofing_results,
:context,
:stages,
:resolution,
:success,
)

if ssn_rate_limiter.limited?
Expand All @@ -93,10 +108,14 @@ def idv_failure(result)
elsif resolution_rate_limiter.limited?
idv_failure_log_rate_limited(:idv_resolution)
redirect_to rate_limited_url
elsif proofing_results_exception.present? && is_mva_exception
elsif has_exception && is_mva_exception
idv_failure_log_warning
redirect_to state_id_warning_url
elsif proofing_results_exception.present?
elsif (has_exception && is_threatmetrix_exception) ||
(!has_exception && resolution_failed)
idv_failure_log_warning
redirect_to warning_url
elsif has_exception
idv_failure_log_error
redirect_to exception_url
else
Expand Down
124 changes: 124 additions & 0 deletions spec/controllers/idv/verify_info_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
include FlowPolicyHelper

let(:user) { create(:user) }

let(:analytics_hash) do
{
analytics_id: 'Doc Auth',
Expand Down Expand Up @@ -144,6 +145,7 @@
context 'when proofing_device_profiling is enabled' do
let(:threatmetrix_client_id) { 'threatmetrix_client' }
let(:review_status) { 'pass' }

let(:idv_result) do
{
context: {
Expand Down Expand Up @@ -253,6 +255,69 @@
end
end

context 'when there is a threatmetrix exception' do
let(:review_status) { nil }

let(:idv_result) do
{
context: {
device_profiling_adjudication_reason: 'device_profiling_exception',
errors: {},
stages: {
threatmetrix: {
client: nil,
errors: {},
exception: "Unexpected ThreatMetrix review_status value: #{review_status}",
response_body: nil,
review_status:,
success: false,
transaction_id: nil,
},
},
},
success: false,
}
end

it 'sets the review status in the idv session' do
get :show
expect(controller.idv_session.threatmetrix_review_status).to be_nil
end

it 'redirects to warning_url' do
get :show

expect(response).to redirect_to idv_session_errors_warning_url

expect(@analytics).to have_logged_event(
'IdV: doc auth warning visited',
step_name: 'verify_info',
remaining_submit_attempts: kind_of(Integer),
)
end

it 'logs the analytics event with the device profiling exception' do
get :show

expect(@analytics).to have_logged_event(
'IdV: doc auth verify proofing results',
hash_including(
success: false,
proofing_results: hash_including(
context: hash_including(
device_profiling_adjudication_reason: 'device_profiling_exception',
stages: hash_including(
threatmetrix: hash_including(
exception: match(/\S+/),
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

A/N: I've only ever found 2 variants of the actual exception message sent to us, but didn't think a stricter match was really necessary as we don't inspect the exception message at all.

),
),
),
),
),
)
end
end

context 'when threatmetrix response is Reject' do
let(:review_status) { 'reject' }

Expand Down Expand Up @@ -427,6 +492,65 @@
end
end

context 'when the resolution proofing job fails and there is no exception' do
before do
allow(controller).to receive(:load_async_state).and_return(async_state)
end

let(:document_capture_session) do
DocumentCaptureSession.create(user:)
end

let(:async_state) do
# Here we're trying to match the store to redis -> read from redis flow this data travels
adjudicated_result = Proofing::Resolution::ResultAdjudicator.new(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Using the ResultAdjudicator directly here is a Good Idea

state_id_result: Proofing::StateIdResult.new(
success: true,
errors: {},
exception: nil,
vendor_name: :aamva,
transaction_id: 'abc123',
verified_attributes: [],
),
device_profiling_result: Proofing::DdpResult.new(success: true),
ipp_enrollment_in_progress: true,
residential_resolution_result: Proofing::Resolution::Result.new(success: true),
resolution_result: Proofing::Resolution::Result.new(
success: false,
errors: {
base: [
"Verification failed with code: 'priority.scoring.model.verification.fail'",
],
},
),
same_address_as_id: true,
should_proof_state_id: true,
applicant_pii: Idp::Constants::MOCK_IDV_APPLICANT_WITH_SSN,
).adjudicated_result.to_h

document_capture_session.create_proofing_session

document_capture_session.store_proofing_result(adjudicated_result)

document_capture_session.load_proofing_result
end

it 'renders the warning page' do
get :show
expect(response).to redirect_to(idv_session_errors_warning_url)
end

it 'logs an event' do
get :show

expect(@analytics).to have_logged_event(
'IdV: doc auth warning visited',
step_name: 'verify_info',
remaining_submit_attempts: kind_of(Numeric),
)
end
end

context 'when the resolution proofing job has not completed' do
let(:async_state) do
ProofingSessionAsyncResult.new(status: ProofingSessionAsyncResult::IN_PROGRESS)
Expand Down
6 changes: 3 additions & 3 deletions spec/features/idv/threat_metrix_pending_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@
end
end

scenario 'users pending ThreatMetrix No Result, it results in an error', :js do
scenario 'users pending ThreatMetrix No Result, it results in an error but shows warning', :js do
freeze_time do
user = create(:user, :fully_registered)
visit_idp_from_ial1_oidc_sp(
Expand All @@ -117,8 +117,8 @@
complete_ssn_step
complete_verify_step

expect(page).to have_content(t('idv.failure.sessions.exception'))
expect(page).to have_current_path(idv_session_errors_exception_path)
expect(page).to have_content(t('idv.failure.sessions.warning'))
expect(page).to have_current_path(idv_session_errors_warning_path)
end
end

Expand Down