Skip to content

Commit

Permalink
LG-14007: handle redirect from socure (#11463)
Browse files Browse the repository at this point in the history
LG-14007: Handle redirect from CaptureApp

Upon redirect from the Socure CaptureApp, we load the result stored in
the DocumentCaptureSession, and if successful, redirect to the SSN entry
step.

- switch callback to a GET
- extract handle_stored_result to the DocumentCaptureConcern
- mv `cancel_establishing_in_person_enrollments` to the concern and call from socure doc cap controller

changelog: Upcoming Features, Identity Verification, Handle Socure handoff.

---------

Co-authored-by: John Maxwell <john.maxwell@gsa.gov>
  • Loading branch information
solipet and jmax-gsa authored Nov 8, 2024
1 parent a4d5f77 commit 79964cb
Show file tree
Hide file tree
Showing 10 changed files with 105 additions and 56 deletions.
17 changes: 17 additions & 0 deletions app/controllers/concerns/idv/document_capture_concern.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@ module DocumentCaptureConcern

include DocAuthVendorConcern

def handle_stored_result(user: current_user, store_in_session: true)
if stored_result&.success? && selfie_requirement_met?
save_proofing_components(user)
extract_pii_from_doc(user, store_in_session: store_in_session)
flash[:success] = t('doc_auth.headings.capture_complete')
successful_response
else
extra = { stored_result_present: stored_result.present? }
failure(I18n.t('doc_auth.errors.general.network_error'), extra)
end
end

def save_proofing_components(user)
return unless user

Expand Down Expand Up @@ -77,5 +89,10 @@ def track_document_issuing_state(user, state)
doc_auth_log.state = state
doc_auth_log.save!
end

def cancel_establishing_in_person_enrollments(user: current_user)
UspsInPersonProofing::EnrollmentHelper.
cancel_stale_establishing_enrollments_for_user(user)
end
end
end
17 changes: 0 additions & 17 deletions app/controllers/idv/document_capture_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,6 @@ def self.step_info

private

def cancel_establishing_in_person_enrollments
UspsInPersonProofing::EnrollmentHelper.
cancel_stale_establishing_enrollments_for_user(current_user)
end

def analytics_arguments
{
flow_path: flow_path,
Expand All @@ -106,18 +101,6 @@ def analytics_arguments
}.merge(ab_test_analytics_buckets)
end

def handle_stored_result
if stored_result&.success? && selfie_requirement_met?
save_proofing_components(current_user)
extract_pii_from_doc(current_user, store_in_session: true)
flash[:success] = t('doc_auth.headings.capture_complete')
successful_response
else
extra = { stored_result_present: stored_result.present? }
failure(I18n.t('doc_auth.errors.general.network_error'), extra)
end
end

def allow_direct_ipp?
return false unless idv_session.welcome_visited &&
idv_session.idv_consent_given?
Expand Down
17 changes: 4 additions & 13 deletions app/controllers/idv/hybrid_mobile/document_capture_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ def show

def update
document_capture_session.confirm_ocr
result = handle_stored_result
result = handle_stored_result(
user: document_capture_user,
store_in_session: false,
)

analytics.idv_doc_auth_document_capture_submitted(**result.to_h.merge(analytics_arguments))

Expand All @@ -33,7 +36,6 @@ def update

# rate limiting redirect is in ImageUploadResponsePresenter
if result.success?
flash[:success] = t('doc_auth.headings.capture_complete')
redirect_to idv_hybrid_mobile_capture_complete_url
else
redirect_to idv_hybrid_mobile_document_capture_url
Expand Down Expand Up @@ -66,17 +68,6 @@ def analytics_arguments
)
end

def handle_stored_result
if stored_result&.success? && selfie_requirement_met?
save_proofing_components(document_capture_user)
extract_pii_from_doc(document_capture_user)
successful_response
else
extra = { stored_result_present: stored_result.present? }
failure(I18n.t('doc_auth.errors.general.network_error'), extra)
end
end

def confirm_document_capture_needed
return unless stored_result&.success?
return if redo_document_capture_pending?
Expand Down
36 changes: 34 additions & 2 deletions app/controllers/idv/socure/document_capture_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def show
# document request
document_request = DocAuth::Socure::Requests::DocumentRequest.new(
document_capture_session_uuid: document_capture_session_uuid,
redirect_url: idv_socure_document_capture_url,
redirect_url: idv_socure_document_capture_update_url,
language: I18n.locale,
)

Expand Down Expand Up @@ -61,7 +61,25 @@ def show
end

def update
render plain: 'stub to ensure Socure callback exists and the route works'
clear_future_steps!
idv_session.redo_document_capture = nil # done with this redo
# Not used in standard flow, here for data consistency with hybrid flow.
document_capture_session.confirm_ocr

result = handle_stored_result
# TODO: new analytics event?
analytics.idv_doc_auth_document_capture_submitted(**result.to_h.merge(analytics_arguments))

Funnel::DocAuth::RegisterStep.new(current_user.id, sp_session[:issuer]).
call('socure_document_capture', :update, true)

cancel_establishing_in_person_enrollments

if result.success?
redirect_to idv_ssn_url
else
redirect_to idv_socure_document_capture_url
end
end

def self.step_info
Expand All @@ -85,6 +103,20 @@ def self.step_info
end,
)
end

private

def analytics_arguments
{
flow_path: flow_path,
step: 'socure_document_capture',
analytics_id: 'Doc Auth',
redo_document_capture: idv_session.redo_document_capture,
skip_hybrid_handoff: idv_session.skip_hybrid_handoff,
liveness_checking_required: resolved_authn_context_result.facial_match?,
selfie_check_required: resolved_authn_context_result.facial_match?,
}.merge(ab_test_analytics_buckets)
end
end
end
end
27 changes: 16 additions & 11 deletions app/controllers/socure_webhook_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,23 @@ def create

private

def process_webhook_event
case event[:eventType]
when 'DOCUMENTS_UPLOADED'
increment_rate_limiter
fetch_results
end
end

def fetch_results
dcs = document_capture_session
raise 'DocumentCaptureSession not found' if dcs.blank?

SocureDocvResultsJob.perform_later(document_capture_session_uuid: dcs.uuid)
if IdentityConfig.store.ruby_workers_idv_enabled
SocureDocvResultsJob.perform_later(document_capture_session_uuid: dcs.uuid)
else
SocureDocvResultsJob.perform_now(document_capture_session_uuid: dcs.uuid)
end
end

def check_token
Expand Down Expand Up @@ -74,14 +86,6 @@ def log_webhook_receipt
)
end

def process_webhook_event
case event[:eventType]
when 'DOCUMENTS_UPLOADED'
increment_rate_limiter
fetch_results
end
end

def increment_rate_limiter
if document_capture_session.present?
rate_limiter.increment!
Expand All @@ -90,8 +94,9 @@ def increment_rate_limiter
end

def document_capture_session
token = event[:docvTransactionToken] || event[:docVTransactionToken]
@document_capture_session ||= DocumentCaptureSession.find_by(
socure_docv_transaction_token: event[:docvTransactionToken],
socure_docv_transaction_token: token,
)
end

Expand All @@ -109,7 +114,7 @@ def rate_limiter
def socure_params
params.permit(
event: [:created, :customerUserId, :eventType, :referenceId,
:docvTransactionToken],
:docvTransactionToken, :docVTransactionToken],
)
end
end
2 changes: 1 addition & 1 deletion app/services/doc_auth/socure/requests/document_request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def lang(language)

def body
redirect = {
method: 'POST',
method: 'GET',
url: redirect_url,
}

Expand Down
2 changes: 1 addition & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@
get '/document_capture' => 'document_capture#show'
put '/document_capture' => 'document_capture#update'
get '/socure/document_capture' => 'socure/document_capture#show'
post '/socure/document_capture' => 'socure/document_capture#update'
get '/socure/document_capture_update' => 'socure/document_capture#update', as: :socure_document_capture_update
# This route is included in SMS messages sent to users who start the IdV hybrid flow. It
# should be kept short, and should not include underscores ("_").
get '/documents' => 'hybrid_mobile/entry#show', as: :hybrid_mobile_entry
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@
config: {
documentType: 'license',
redirect: {
method: 'POST',
method: 'GET',
url: idv_hybrid_mobile_socure_document_capture_url,
},
language: expected_language,
Expand All @@ -143,7 +143,7 @@
config: {
documentType: 'license',
redirect: {
method: 'POST',
method: 'GET',
url: idv_hybrid_mobile_socure_document_capture_url,
},
language: 'zh-cn',
Expand Down
37 changes: 29 additions & 8 deletions spec/controllers/idv/socure/document_capture_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,17 @@
let(:idv_vendor) { Idp::Constants::Vendors::SOCURE }
let(:fake_socure_endpoint) { 'https://fake-socure.test' }
let(:user) { create(:user) }
let(:stored_result) { nil }
let(:doc_auth_success) { true }
let(:stored_result) do
DocumentCaptureSessionResult.new(
id: SecureRandom.uuid,
success: doc_auth_success,
doc_auth_success: doc_auth_success,
selfie_status: :none,
pii: { first_name: 'Testy', last_name: 'Testerson' },
attention_with_barcode: false,
)
end
let(:socure_enabled) { true }

let(:document_capture_session) do
Expand All @@ -23,6 +33,7 @@
and_return(fake_socure_endpoint)
allow(IdentityConfig.store).to receive(:doc_auth_vendor).and_return(idv_vendor)
allow(IdentityConfig.store).to receive(:doc_auth_vendor_default).and_return(idv_vendor)
allow_any_instance_of(ApplicationController).to receive(:current_user).and_return(user)

allow(subject).to receive(:stored_result).and_return(stored_result)

Expand Down Expand Up @@ -101,7 +112,7 @@
expect(request_class).to have_received(:new).
with(
document_capture_session_uuid: expected_uuid,
redirect_url: idv_socure_document_capture_url,
redirect_url: idv_socure_document_capture_update_url,
language: expected_language,
)
end
Expand All @@ -122,8 +133,8 @@
config: {
documentType: 'license',
redirect: {
method: 'POST',
url: idv_socure_document_capture_url,
method: 'GET',
url: idv_socure_document_capture_update_url,
},
language: :en,
},
Expand All @@ -145,8 +156,8 @@
config: {
documentType: 'license',
redirect: {
method: 'POST',
url: idv_socure_document_capture_url,
method: 'GET',
url: idv_socure_document_capture_update_url,
},
language: 'zh-cn',
},
Expand Down Expand Up @@ -264,9 +275,19 @@

describe '#update' do
it 'returns OK (200)' do
post(:update)
get(:update)

expect(response).to redirect_to(idv_ssn_path)
end

expect(response).to have_http_status(:ok)
context 'when doc auth fails' do
let(:doc_auth_success) { false }

it 'redirects to document capture' do
get(:update)

expect(response).to redirect_to(idv_socure_document_capture_path)
end
end

context 'when socure is disabled' do
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
documentType: document_type,
redirect:
{
method: 'POST',
method: 'GET',
url: redirect_url,
},
language: language,
Expand Down

0 comments on commit 79964cb

Please sign in to comment.