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
14 changes: 14 additions & 0 deletions app/controllers/concerns/idv/document_capture_concern.rb
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,20 @@ def redirect_to_correct_vendor(vendor, in_hybrid_mobile)
redirect_to correct_path
end

def fetch_test_verification_data
return unless IdentityConfig.store.socure_docv_verification_data_test_mode

docv_transaction_token_override = params.permit(:docv_token)[:docv_token]
return unless IdentityConfig.store.socure_docv_verification_data_test_mode_tokens.
include?(docv_transaction_token_override)

SocureDocvResultsJob.perform_now(
document_capture_session_uuid:,
docv_transaction_token_override:,
async: true,
)
end

private

def track_document_issuing_state(user, state)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class DocumentCaptureController < ApplicationController
before_action :check_valid_document_capture_session, except: [:update]
before_action -> { redirect_to_correct_vendor(Idp::Constants::Vendors::SOCURE, true) },
only: :show
before_action :fetch_test_verification_data, only: [:update]

def show
Funnel::DocAuth::RegisterStep.new(document_capture_user.id, sp_session[:issuer]).
Expand Down
1 change: 1 addition & 0 deletions app/controllers/idv/socure/document_capture_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class DocumentCaptureController < ApplicationController
before_action :confirm_step_allowed
before_action -> { redirect_to_correct_vendor(Idp::Constants::Vendors::SOCURE, false) },
only: :show
before_action :fetch_test_verification_data, only: [:update]

# reconsider and maybe remove these when implementing the real
# update handler
Expand Down
6 changes: 4 additions & 2 deletions app/jobs/socure_docv_results_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
class SocureDocvResultsJob < ApplicationJob
queue_as :high_socure_docv

attr_reader :document_capture_session_uuid, :async
attr_reader :document_capture_session_uuid, :async, :docv_transaction_token_override

# @param [String] document_capture_session_uuid
def perform(document_capture_session_uuid:, async: true)
def perform(document_capture_session_uuid:, async: true, docv_transaction_token_override: nil)
@document_capture_session_uuid = document_capture_session_uuid
@async = async
@docv_transaction_token_override = docv_transaction_token_override

raise "DocumentCaptureSession not found: #{document_capture_session_uuid}" unless
document_capture_session
Expand Down Expand Up @@ -51,6 +52,7 @@ def log_verification_request(docv_result_response:, vendor_request_time_in_ms:)
def socure_document_verification_result
DocAuth::Socure::Requests::DocvResultRequest.new(
document_capture_session_uuid:,
docv_transaction_token_override:,
).fetch
end

Expand Down
19 changes: 17 additions & 2 deletions app/services/doc_auth/socure/requests/docv_result_request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,13 @@ module Requests
class DocvResultRequest < DocAuth::Socure::Request
attr_reader :document_capture_session_uuid, :biometric_comparison_required

def initialize(document_capture_session_uuid:, biometric_comparison_required: false)
def initialize(
document_capture_session_uuid:,
docv_transaction_token_override: nil,
biometric_comparison_required: false
)
@document_capture_session_uuid = document_capture_session_uuid
@docv_transaction_token_override = docv_transaction_token_override
@biometric_comparison_required = biometric_comparison_required
end

Expand All @@ -16,7 +21,7 @@ def initialize(document_capture_session_uuid:, biometric_comparison_required: fa
def body
{
modules: ['documentverification'],
docvTransactionToken: document_capture_session.socure_docv_transaction_token,
docvTransactionToken: docv_transaction_token,
}.to_json
end

Expand Down Expand Up @@ -60,6 +65,16 @@ def endpoint
def metric_name
'socure_id_plus_document_verification'
end

def docv_transaction_token
if IdentityConfig.store.socure_docv_verification_data_test_mode &&
IdentityConfig.store.socure_docv_verification_data_test_mode_tokens.
include?(@docv_transaction_token_override)
return @docv_transaction_token_override
end

document_capture_session.socure_docv_transaction_token
end
end
end
end
Expand Down
2 changes: 2 additions & 0 deletions config/application.yml.default
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,8 @@ sign_in_user_id_per_ip_max_attempts: 50
skip_encryption_allowed_list: '["urn:gov:gsa:SAML:2.0.profiles:sp:sso:dev", "urn:gov:gsa:SAML:2.0.profiles:sp:sso:int"]'
socure_docv_document_request_endpoint: ''
socure_docv_enabled: false
socure_docv_verification_data_test_mode: false
socure_docv_verification_data_test_mode_tokens: '[]'
socure_docv_webhook_secret_key: ''
socure_docv_webhook_secret_key_queue: '[]'
socure_idplus_api_key: ''
Expand Down
2 changes: 2 additions & 0 deletions lib/identity_config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,8 @@ def self.store
config.add(:recommend_webauthn_platform_for_sms_ab_test_authentication_percent, type: :integer)
config.add(:socure_docv_document_request_endpoint, type: :string)
config.add(:socure_docv_enabled, type: :boolean)
config.add(:socure_docv_verification_data_test_mode, type: :boolean)
config.add(:socure_docv_verification_data_test_mode_tokens, type: :json)
config.add(:socure_docv_webhook_secret_key_queue, type: :json)
config.add(:socure_docv_webhook_secret_key, type: :string)
config.add(:socure_idplus_api_key, type: :string)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
end
let(:document_capture_session_uuid) { document_capture_session&.uuid }

let(:socure_docv_verification_data_test_mode) { false }

before do
allow(IdentityConfig.store).to receive(:socure_docv_enabled).
and_return(socure_docv_enabled)
Expand All @@ -33,6 +35,14 @@
session[:doc_capture_user_id] = user&.id
session[:document_capture_session_uuid] = document_capture_session_uuid

allow(IdentityConfig.store).
to receive(:socure_docv_verification_data_test_mode).
and_return(socure_docv_verification_data_test_mode)

unless IdentityConfig.store.socure_docv_verification_data_test_mode
expect(IdentityConfig.store).not_to receive(:socure_docv_verification_data_test_mode_tokens)
end

stub_analytics
end

Expand Down Expand Up @@ -359,5 +369,48 @@
end
end
end

context 'when socure_docv_verification_data_test_mode is enabled' do
let(:test_token) { '12345' }
let(:socure_docv_verification_data_test_mode) { true }

before do
ActiveJob::Base.queue_adapter = :test
allow(IdentityConfig.store).
to receive(:socure_docv_verification_data_test_mode_tokens).
and_return([test_token])

stub_request(
:post,
"#{IdentityConfig.store.socure_idplus_base_url}/api/3.0/EmailAuthScore",
).
with(body: { modules: ['documentverification'], docvTransactionToken: test_token }.
to_json).
to_return(
headers: {
'Content-Type' => 'application/json',
},
body: SocureDocvFixtures.pass_json,
)
end

context 'when a token is provided from the allow list' do
it 'performs SocureDocvResultsJob' do
expect { get(:update, params: { docv_token: test_token }) }.
not_to have_enqueued_job(SocureDocvResultsJob) # is synchronous

expect(document_capture_session.reload.load_result).not_to be_nil
end
end

context 'when a token is provided not on the allow list' do
it 'performs SocureDocvResultsJob' do
expect { get(:update, params: { docv_token: 'rando-token' }) }.
not_to have_enqueued_job(SocureDocvResultsJob)

expect(document_capture_session.reload.load_result).to be_nil
end
end
end
end
end
52 changes: 52 additions & 0 deletions spec/controllers/idv/socure/document_capture_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
)
end

let(:socure_docv_verification_data_test_mode) { false }

before do
allow(IdentityConfig.store).to receive(:socure_docv_enabled).
and_return(socure_docv_enabled)
Expand All @@ -44,6 +46,13 @@
allow(subject).to receive(:user_session).and_return(user_session)

subject.idv_session.document_capture_session_uuid = document_capture_session.uuid
allow(IdentityConfig.store).
to receive(:socure_docv_verification_data_test_mode).
and_return(socure_docv_verification_data_test_mode)

unless IdentityConfig.store.socure_docv_verification_data_test_mode
expect(IdentityConfig.store).not_to receive(:socure_docv_verification_data_test_mode_tokens)
end

stub_analytics
end
Expand Down Expand Up @@ -341,6 +350,49 @@
expect(response.body).to eq('Technical difficulties!!!')
end
end

context 'when socure_docv_verification_data_test_mode is enabled' do
let(:test_token) { '12345' }
let(:socure_docv_verification_data_test_mode) { true }

before do
ActiveJob::Base.queue_adapter = :test
allow(IdentityConfig.store).
to receive(:socure_docv_verification_data_test_mode_tokens).
and_return([test_token])

stub_request(
:post,
"#{IdentityConfig.store.socure_idplus_base_url}/api/3.0/EmailAuthScore",
).
with(body: { modules: ['documentverification'], docvTransactionToken: test_token }.
to_json).
to_return(
headers: {
'Content-Type' => 'application/json',
},
body: SocureDocvFixtures.pass_json,
)
end

context 'when a token is provided from the allow list' do
it 'performs SocureDocvResultsJob' do
expect { get(:update, params: { docv_token: test_token }) }.
not_to have_enqueued_job(SocureDocvResultsJob) # is synchronous

expect(document_capture_session.reload.load_result).not_to be_nil
end
end

context 'when a token is provided not on the allow list' do
it 'performs SocureDocvResultsJob' do
expect { get(:update, params: { docv_token: 'rando-token' }) }.
not_to have_enqueued_job(SocureDocvResultsJob)

expect(document_capture_session.reload.load_result).to be_nil
end
end
end
end

context 'when socure is disabled' do
Expand Down
76 changes: 65 additions & 11 deletions spec/features/idv/doc_auth/socure_document_capture_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
let(:socure_docv_webhook_secret_key) { 'socure_docv_webhook_secret_key' }
let(:fake_socure_docv_document_request_endpoint) { 'https://fake-socure.test/document-request' }
let(:fake_socure_document_capture_app_url) { 'https://verify.fake-socure.test/something' }
let(:socure_docv_verification_data_test_mode) { false }

before(:each) do
allow(IdentityConfig.store).to receive(:socure_docv_enabled).and_return(true)
Expand All @@ -24,23 +25,19 @@
allow(IdentityConfig.store).to receive(:ruby_workers_idv_enabled).and_return(false)
allow_any_instance_of(ApplicationController).to receive(:analytics).and_return(fake_analytics)
@docv_transaction_token = stub_docv_document_request
allow(IdentityConfig.store).to receive(:socure_docv_verification_data_test_mode).
and_return(socure_docv_verification_data_test_mode)
end

before(:all) do
@user = user_with_2fa
end

after(:all) { @user.destroy }

context 'happy path' do
before do
stub_docv_verification_data_pass
@pass_stub = stub_docv_verification_data_pass(docv_transaction_token: @docv_transaction_token)
end

context 'standard desktop flow' do
before do
visit_idp_from_oidc_sp_with_ial2
sign_in_and_2fa_user(@user)
@user = sign_in_and_2fa_user
complete_doc_auth_steps_before_document_capture_step
click_idv_continue
end
Expand Down Expand Up @@ -122,6 +119,7 @@
docv_transaction_token: @docv_transaction_token,
)

visit idv_socure_document_capture_update_path
expect(DocAuthLog.find_by(user_id: @user.id).state).to be_nil
end

Expand All @@ -131,15 +129,68 @@
docv_transaction_token: @docv_transaction_token,
)

visit idv_socure_document_capture_update_path
expect(DocAuthLog.find_by(user_id: @user.id).state).not_to be_nil
end

context 'when socure_docv_verification_data_test_mode is enabled' do
let(:test_token) { 'valid-test-token' }
let(:socure_docv_verification_data_test_mode) { true }
before do
allow(IdentityConfig.store).to receive(:socure_docv_verification_data_test_mode_tokens).
and_return([test_token])
DocAuth::Mock::DocAuthMockClient.reset!
end

context 'when a valid test token is used' do
it 'fetches verificationdata using override docvToken in request',
allow_browser_log: true do
remove_request_stub(@pass_stub)
stub_docv_verification_data_pass(docv_transaction_token: test_token)

visit idv_socure_document_capture_update_path(docv_token: test_token)
expect(page).to have_current_path(idv_ssn_url)

expect(DocAuthLog.find_by(user_id: @user.id).state).to eq('NY')

fill_out_ssn_form_ok
click_idv_continue
complete_verify_step
expect(page).to have_current_path(idv_phone_url)
end
end

context 'when an invalid test token is used' do
let(:invalid_token) { 'invalid-token' }
it 'waits to fetch verificationdata using docv capture session token' do
visit idv_socure_document_capture_update_path(docv_token: invalid_token)

expect(page).to have_current_path(
idv_socure_document_capture_update_path(docv_token: invalid_token),
)
socure_docv_upload_documents(
docv_transaction_token: @docv_transaction_token,
)
visit idv_socure_document_capture_update_path(docv_token: invalid_token)

expect(page).to have_current_path(idv_ssn_url)

expect(DocAuthLog.find_by(user_id: @user.id).state).to eq('NY')

fill_out_ssn_form_ok
click_idv_continue
complete_verify_step
expect(page).to have_current_path(idv_phone_url)
end
end
end
end

context 'standard mobile flow' do
it 'proceeds to the next page with valid info' do
perform_in_browser(:mobile) do
visit_idp_from_oidc_sp_with_ial2
sign_in_and_2fa_user(@user)
@user = sign_in_and_2fa_user
complete_doc_auth_steps_before_document_capture_step

expect(page).to have_current_path(idv_socure_document_capture_url)
Expand All @@ -164,10 +215,13 @@

shared_examples 'a properly categorized Socure error' do |socure_error_code, expected_header_key|
before do
stub_docv_verification_data_fail_with([socure_error_code])
stub_docv_verification_data_fail_with(
docv_transaction_token: @docv_transaction_token,
errors: [socure_error_code],
)

visit_idp_from_oidc_sp_with_ial2
sign_in_and_2fa_user(@user)
@user = sign_in_and_2fa_user

complete_doc_auth_steps_before_document_capture_step

Expand Down
Loading