diff --git a/app/controllers/concerns/idv/doc_auth_vendor_concern.rb b/app/controllers/concerns/idv/doc_auth_vendor_concern.rb index 25225c3d6a4..079a828753b 100644 --- a/app/controllers/concerns/idv/doc_auth_vendor_concern.rb +++ b/app/controllers/concerns/idv/doc_auth_vendor_concern.rb @@ -6,8 +6,32 @@ module DocAuthVendorConcern # @returns[String] String identifying the vendor to use for doc auth. def doc_auth_vendor - bucket = ab_test_bucket(:DOC_AUTH_VENDOR) + if resolved_authn_context_result.facial_match? + if doc_auth_vendor_enabled?(Idp::Constants::Vendors::LEXIS_NEXIS) + bucket = :lexis_nexis + elsif doc_auth_vendor_enabled?(Idp::Constants::Vendors::MOCK) + bucket = :mock + else + return nil + end + else + bucket = ab_test_bucket(:DOC_AUTH_VENDOR) + end DocAuthRouter.doc_auth_vendor_for_bucket(bucket) end + + def doc_auth_vendor_enabled?(vendor) + return true if IdentityConfig.store.doc_auth_vendor_default == vendor + return false unless IdentityConfig.store.doc_auth_vendor_switching_enabled + + case vendor + when Idp::Constants::Vendors::SOCURE + IdentityConfig.store.doc_auth_vendor_socure_percent > 0 + when Idp::Constants::Vendors::LEXIS_NEXIS + IdentityConfig.store.doc_auth_vendor_lexis_nexis_percent > 0 + else + false + end + end end end diff --git a/app/services/doc_auth_router.rb b/app/services/doc_auth_router.rb index a4c43f1d75f..c985bf876d9 100644 --- a/app/services/doc_auth_router.rb +++ b/app/services/doc_auth_router.rb @@ -201,6 +201,8 @@ def self.doc_auth_vendor_for_bucket(bucket) Idp::Constants::Vendors::SOCURE when :lexis_nexis Idp::Constants::Vendors::LEXIS_NEXIS + when :mock + Idp::Constants::Vendors::MOCK else # e.g., nil IdentityConfig.store.doc_auth_vendor_default end diff --git a/spec/controllers/idv/document_capture_controller_spec.rb b/spec/controllers/idv/document_capture_controller_spec.rb index 88d1ca61523..50b01750c8d 100644 --- a/spec/controllers/idv/document_capture_controller_spec.rb +++ b/spec/controllers/idv/document_capture_controller_spec.rb @@ -117,6 +117,7 @@ end let(:idv_vendor) { Idp::Constants::Vendors::LEXIS_NEXIS } + let(:vendor_switching_enabled) { true } before do allow(IdentityConfig.store).to receive(:doc_auth_vendor).and_return( @@ -125,6 +126,9 @@ allow(IdentityConfig.store).to receive(:doc_auth_vendor_default).and_return( idv_vendor, ) + allow(IdentityConfig.store).to receive(:doc_auth_vendor_switching_enabled).and_return( + vendor_switching_enabled, + ) end it 'has non-nil presenter' do @@ -142,6 +146,23 @@ end end + context 'socure is the default vendor but facial match is required' do + let(:idv_vendor) { Idp::Constants::Vendors::SOCURE } + let(:vot) { 'Pb' } + + before do + resolved_authn_context = Vot::Parser.new(vector_of_trust: vot).parse + allow(controller).to receive(:resolved_authn_context_result). + and_return(resolved_authn_context) + end + + it 'does not redirect to Socure controller' do + get :show + + expect(response).to_not redirect_to idv_socure_document_capture_url + end + end + it 'renders the show template' do expect(subject).to receive(:render).with( :show, diff --git a/spec/controllers/idv/hybrid_mobile/entry_controller_spec.rb b/spec/controllers/idv/hybrid_mobile/entry_controller_spec.rb index 8d43b38e37f..15d1bb50191 100644 --- a/spec/controllers/idv/hybrid_mobile/entry_controller_spec.rb +++ b/spec/controllers/idv/hybrid_mobile/entry_controller_spec.rb @@ -56,9 +56,29 @@ {} end let(:idv_vendor) { Idp::Constants::Vendors::MOCK } + let(:vendor_switching_enabled) { true } + let(:lexis_nexis_percent) { 100 } + let(:acr_values) do + [ + Saml::Idp::Constants::IAL2_AUTHN_CONTEXT_CLASSREF, + Saml::Idp::Constants::DEFAULT_AAL_AUTHN_CONTEXT_CLASSREF, + ].join(' ') + end before do + resolved_authn_context = AuthnContextResolver.new( + user: user, + service_provider: nil, + vtr: nil, + acr_values: acr_values, + ).result allow(controller).to receive(:session).and_return(session) + allow(controller).to receive(:resolved_authn_context_result). + and_return(resolved_authn_context) + allow(IdentityConfig.store).to receive(:doc_auth_vendor_switching_enabled). + and_return(vendor_switching_enabled) + allow(IdentityConfig.store).to receive(:doc_auth_vendor_lexis_nexis_percent). + and_return(lexis_nexis_percent) get :show, params: { 'document-capture-session': session_uuid } end @@ -70,6 +90,46 @@ end end + context 'facial match is required' do + let(:acr_values) do + [ + Saml::Idp::Constants::IAL2_BIO_REQUIRED_AUTHN_CONTEXT_CLASSREF, + Saml::Idp::Constants::DEFAULT_AAL_AUTHN_CONTEXT_CLASSREF, + ].join(' ') + end + + context 'doc auth vendor is socure with facial match required' do + let(:idv_vendor) { Idp::Constants::Vendors::SOCURE } + + it 'redirects to the lexis nexis first step' do + expect(response).to redirect_to idv_hybrid_mobile_document_capture_url + end + end + + context 'doc auth vendor is mock with facial match required' do + let(:idv_vendor) { Idp::Constants::Vendors::MOCK } + + it 'redirects to the lexis nexis first step' do + expect(response).to redirect_to idv_hybrid_mobile_document_capture_url + end + end + + context 'lexis nexis is disabled' do + let(:idv_vendor) { nil } + let(:vendor_switching_enabled) { false } + let(:lexis_nexis_percent) { 0 } + + before do + allow(IdentityConfig.store).to receive(:doc_auth_vendor_lexis_nexis_percent). + and_return(lexis_nexis_percent) + end + + it 'causes an 404 error' do + expect(response.status).to eq(404) + end + end + end + context 'doc auth vendor is lexis nexis' do let(:idv_vendor) { Idp::Constants::Vendors::LEXIS_NEXIS } @@ -78,6 +138,14 @@ end end + context 'doc auth vendor is mock' do + let(:idv_vendor) { Idp::Constants::Vendors::MOCK } + + it 'redirects to the first step' do + expect(response).to redirect_to idv_hybrid_mobile_document_capture_url + end + end + context 'but we already had a session' do let!(:different_document_capture_session) do DocumentCaptureSession.create!( diff --git a/spec/controllers/idv/hybrid_mobile/socure/document_capture_controller_spec.rb b/spec/controllers/idv/hybrid_mobile/socure/document_capture_controller_spec.rb index 60b77e84bdb..c3a9088a164 100644 --- a/spec/controllers/idv/hybrid_mobile/socure/document_capture_controller_spec.rb +++ b/spec/controllers/idv/hybrid_mobile/socure/document_capture_controller_spec.rb @@ -4,6 +4,7 @@ include FlowPolicyHelper let(:idv_vendor) { Idp::Constants::Vendors::SOCURE } + let(:vendor_switching_enabled) { true } let(:fake_socure_endpoint) { 'https://fake-socure.test' } let(:user) { create(:user) } let(:stored_result) { nil } @@ -24,6 +25,8 @@ 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(IdentityConfig.store).to receive(:doc_auth_vendor_switching_enabled). + and_return(vendor_switching_enabled) allow(subject).to receive(:stored_result).and_return(stored_result) @@ -64,11 +67,37 @@ end context 'when we try to use this controller but we should be using the LN/mock version' do - let(:idv_vendor) { Idp::Constants::Vendors::LEXIS_NEXIS } + context 'when doc_auth_vendor is Lexis Nexis' do + let(:idv_vendor) { Idp::Constants::Vendors::LEXIS_NEXIS } - it 'redirects to the LN/mock controller' do - get :show - expect(response).to redirect_to idv_hybrid_mobile_document_capture_url + it 'redirects to the LN/mock controller' do + get :show + expect(response).to redirect_to idv_hybrid_mobile_document_capture_url + end + end + + context 'when facial match is required' do + let(:acr_values) do + [ + Saml::Idp::Constants::IAL2_BIO_REQUIRED_AUTHN_CONTEXT_CLASSREF, + Saml::Idp::Constants::DEFAULT_AAL_AUTHN_CONTEXT_CLASSREF, + ].join(' ') + end + before do + resolved_authn_context = AuthnContextResolver.new( + user: user, + service_provider: nil, + vtr: nil, + acr_values: acr_values, + ).result + allow(controller).to receive(:resolved_authn_context_result). + and_return(resolved_authn_context) + end + + it 'redirects to the LN/mock controller' do + get :show + expect(response).to redirect_to idv_hybrid_mobile_document_capture_url + end end end diff --git a/spec/controllers/idv/socure/document_capture_controller_spec.rb b/spec/controllers/idv/socure/document_capture_controller_spec.rb index e431b493a6a..9e03f8e8cdd 100644 --- a/spec/controllers/idv/socure/document_capture_controller_spec.rb +++ b/spec/controllers/idv/socure/document_capture_controller_spec.rb @@ -4,6 +4,7 @@ include FlowPolicyHelper let(:idv_vendor) { Idp::Constants::Vendors::SOCURE } + let(:vendor_switching_enabled) { true } let(:fake_socure_endpoint) { 'https://fake-socure.test' } let(:user) { create(:user) } let(:doc_auth_success) { true } @@ -33,6 +34,8 @@ 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(IdentityConfig.store).to receive(:doc_auth_vendor_switching_enabled). + and_return(vendor_switching_enabled) allow_any_instance_of(ApplicationController).to receive(:current_user).and_return(user) allow(subject).to receive(:stored_result).and_return(stored_result) @@ -79,11 +82,37 @@ end context 'when we try to use this controller but we should be using the LN/mock version' do - let(:idv_vendor) { Idp::Constants::Vendors::LEXIS_NEXIS } + context 'when doc_auth_vendor is Lexis Nexis' do + let(:idv_vendor) { Idp::Constants::Vendors::LEXIS_NEXIS } - it 'redirects to the LN/mock controller' do - get :show - expect(response).to redirect_to idv_document_capture_url + it 'redirects to the LN/mock controller' do + get :show + expect(response).to redirect_to idv_document_capture_url + end + end + + context 'when facial match is required' do + let(:acr_values) do + [ + Saml::Idp::Constants::IAL2_BIO_REQUIRED_AUTHN_CONTEXT_CLASSREF, + Saml::Idp::Constants::DEFAULT_AAL_AUTHN_CONTEXT_CLASSREF, + ].join(' ') + end + before do + resolved_authn_context = AuthnContextResolver.new( + user: user, + service_provider: nil, + vtr: nil, + acr_values: acr_values, + ).result + allow(controller).to receive(:resolved_authn_context_result). + and_return(resolved_authn_context) + end + + it 'redirects to the LN/mock controller' do + get :show + expect(response).to redirect_to idv_document_capture_url + end end end