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
1 change: 1 addition & 0 deletions app/controllers/concerns/idv/verify_info_concern.rb
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ def async_state_done(current_async_state)
extra: {
address_edited: !!idv_session.address_edited,
address_line2_present: !pii[:address2].blank?,
last_name_spaced: pii[:last_name].split(' ').many?,
previous_ssn_edit_distance: previous_ssn_edit_distance,
pii_like_keypaths: [
[:errors, :ssn],
Expand Down
2 changes: 2 additions & 0 deletions app/controllers/concerns/saml_idp_logout_concern.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ def logout_response

def track_logout_event
sp_initiated = saml_request.present?
attempts_api_tracker.logout_initiated(success: true)

analytics.logout_initiated(
sp_initiated: sp_initiated,
oidc: false,
Expand Down
15 changes: 5 additions & 10 deletions app/controllers/idv/how_to_verify_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ class HowToVerifyController < ApplicationController
include Idv::AvailabilityConcern
include IdvStepConcern
include RenderConditionConcern
include DocAuthVendorConcern

before_action :confirm_step_allowed
before_action :set_how_to_verify_presenter
Expand Down Expand Up @@ -64,9 +65,9 @@ def self.step_info
idv_session.service_provider&.in_person_proofing_enabled
end,
undo_step: ->(idv_session:, user:) {
idv_session.skip_doc_auth_from_how_to_verify = nil
idv_session.opted_in_to_in_person_proofing = nil
},
idv_session.skip_doc_auth_from_how_to_verify = nil
idv_session.opted_in_to_in_person_proofing = nil
},
)
end

Expand Down Expand Up @@ -96,19 +97,13 @@ def set_how_to_verify_presenter
@presenter = Idv::HowToVerifyPresenter.new(
mobile_required: @mobile_required,
selfie_check_required: @selfie_required,
passport_allowed: idv_session.passport_allowed,
)
end

def mobile_required?
idv_session.selfie_check_required ||
document_capture_session.doc_auth_vendor == Idp::Constants::Vendors::SOCURE
end

def document_capture_session
return @document_capture_session if defined?(@document_capture_session)
@document_capture_session = DocumentCaptureSession.find_by(
uuid: idv_session.document_capture_session_uuid,
)
end
end
end
23 changes: 17 additions & 6 deletions app/controllers/idv/welcome_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ class WelcomeController < ApplicationController
include StepIndicatorConcern
include DocAuthVendorConcern

before_action :confirm_step_allowed
before_action :confirm_not_rate_limited
before_action :cancel_previous_in_person_enrollments, only: :show
before_action :update_doc_auth_vendor
before_action :update_passport_allowed,
only: :show,
if: -> { IdentityConfig.store.doc_auth_passports_enabled }
Expand All @@ -20,15 +22,16 @@ def show
Funnel::DocAuth::RegisterStep.new(current_user.id, sp_session[:issuer])
.call('welcome', :view, true)

@presenter = Idv::WelcomePresenter.new(decorated_sp_session)
@presenter = Idv::WelcomePresenter.new(
decorated_sp_session:,
passport_allowed: idv_session.passport_allowed,
)
end

def update
clear_future_steps!
analytics.idv_doc_auth_welcome_submitted(**analytics_arguments)

create_document_capture_session

analytics.idv_doc_auth_welcome_submitted(**analytics_arguments)
idv_session.welcome_visited = true

redirect_to idv_agreement_url
Expand All @@ -39,10 +42,12 @@ def self.step_info
key: :welcome,
controller: self,
next_steps: [:agreement],
preconditions: ->(idv_session:, user:) { !user.gpo_verification_pending_profile? },
preconditions: ->(idv_session:, user:) { true },
undo_step: ->(idv_session:, user:) do
idv_session.welcome_visited = nil
idv_session.document_capture_session_uuid = nil
idv_session.bucketed_doc_auth_vendor = nil
idv_session.passport_allowed = nil
end,
)
end
Expand All @@ -53,6 +58,8 @@ def analytics_arguments
{
step: 'welcome',
analytics_id: 'Doc Auth',
doc_auth_vendor: idv_session.bucketed_doc_auth_vendor,
passport_allowed: idv_session.passport_allowed,
}.merge(ab_test_analytics_buckets)
end

Expand All @@ -72,10 +79,14 @@ def cancel_previous_in_person_enrollments
)
end

def update_doc_auth_vendor
doc_auth_vendor
end

def update_passport_allowed
return if !IdentityConfig.store.doc_auth_passports_enabled
return if resolved_authn_context_result.facial_match?
return if doc_auth_vendor == Idp::Constants::Vendors::SOCURE

idv_session.passport_allowed ||= begin
if dos_passport_api_healthy?(analytics:)
(ab_test_bucket(:DOC_AUTH_PASSPORT) == :passport_allowed)
Expand Down
2 changes: 2 additions & 0 deletions app/controllers/openid_connect/authorization_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,8 @@ def track_events
acr_values: sp_session[:acr_values],
sign_in_duration_seconds:,
)

attempts_api_tracker.login_completed
track_billing_events
end

Expand Down
16 changes: 9 additions & 7 deletions app/controllers/openid_connect/logout_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ def show
original_method: session[:original_method],
)

attempts_api_tracker.logout_initiated(
success: result.success?,
)

if result.success? && redirect_uri
handle_successful_logout_request(result, redirect_uri)
else
Expand All @@ -46,6 +50,9 @@ def delete
redirect_uri = result.extra[:redirect_uri]

analytics.oidc_logout_submitted(**to_event(result))
attempts_api_tracker.logout_initiated(
success: result.success?,
)

if result.success? && redirect_uri
handle_logout(result, redirect_uri)
Expand Down Expand Up @@ -90,12 +97,6 @@ def apply_logout_secure_headers_override(redirect_uri, service_provider)
override_form_action_csp(uris)
end

def require_logout_confirmation?
(logout_params[:id_token_hint].nil? || IdentityConfig.store.reject_id_token_hint_in_logout) &&
logout_params[:client_id] &&
current_user
end

# @return [OpenidConnectLogoutForm]
def build_logout_form
OpenidConnectLogoutForm.new(
Expand All @@ -108,12 +109,13 @@ def build_logout_form
# @param redirect_uri [String] The URL to redirect the user to after logout
def handle_successful_logout_request(result, redirect_uri)
apply_logout_secure_headers_override(redirect_uri, @logout_form.service_provider)
if require_logout_confirmation?
if current_user.present?
analytics.oidc_logout_visited(**to_event(result))

@params = {
client_id: logout_params[:client_id],
post_logout_redirect_uri: logout_params[:post_logout_redirect_uri],
id_token_hint: logout_params[:id_token_hint],
}
@params[:state] = logout_params[:state] if !logout_params[:state].nil?
@service_provider_name = @logout_form.service_provider&.friendly_name
Expand Down
2 changes: 2 additions & 0 deletions app/controllers/saml_idp_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,8 @@ def track_events
acr_values: sp_session[:acr_values],
sign_in_duration_seconds:,
)

attempts_api_tracker.login_completed
track_billing_events
end

Expand Down
2 changes: 2 additions & 0 deletions app/controllers/sign_out_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ class SignOutController < ApplicationController

def destroy
analytics.logout_initiated(method: 'cancel link')
attempts_api_tracker.logout_initiated(success: true)

url_after_cancellation = decorated_sp_session.cancel_link_url
sign_out
flash[:success] = t('devise.sessions.signed_out')
Expand Down
9 changes: 3 additions & 6 deletions app/controllers/users/sessions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,9 @@ def create
end

def destroy
if request.method == 'GET' && IdentityConfig.store.disable_logout_get_request
redirect_to root_path
else
analytics.logout_initiated(sp_initiated: false, oidc: false)
super
end
analytics.logout_initiated(sp_initiated: false, oidc: false)
attempts_api_tracker.logout_initiated(success: true)
super
end

def analytics_user
Expand Down
33 changes: 29 additions & 4 deletions app/forms/idv/api_image_upload_form.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ def submit

client_response = nil
doc_pii_response = nil
passport_response = nil

if form_response.success?
client_response = post_images_to_client
Expand All @@ -46,13 +47,19 @@ def submit

if client_response.success?
doc_pii_response = validate_pii_from_doc(client_response)

if doc_pii_response.success? &&
doc_pii_response.pii_from_doc[:state_id_type] == 'passport'
passport_response = validate_mrz(client_response)
end
end
end

response = determine_response(
form_response: form_response,
client_response: client_response,
doc_pii_response: doc_pii_response,
form_response:,
client_response:,
doc_pii_response:,
passport_response:,
)

failed_fingerprints = store_failed_images(client_response, doc_pii_response)
Expand Down Expand Up @@ -157,6 +164,22 @@ def validate_pii_from_doc(client_response)
response
end

def validate_mrz(client_response)
response = DocAuth::Dos::Requests::MrzRequest.new(mrz: client_response.pii_from_doc.mrz).fetch

analytics.idv_dos_passport_verification(
document_type:,
remaining_submit_attempts:,
submit_attempts:,
user_id: user_uuid,
response: response.extra[:response],
success: response.success?,
)

response.extra.merge!(extra_attributes)
response
end

def doc_side_classification(client_response)
side_info = {}.merge(client_response&.extra&.[](:classification_info) || {})
side_info.transform_keys(&:downcase).symbolize_keys
Expand Down Expand Up @@ -227,13 +250,15 @@ def processed_selfie_attempts_data
{ selfie_attempts: past_selfie_count + processed_selfie_count }
end

def determine_response(form_response:, client_response:, doc_pii_response:)
def determine_response(form_response:, client_response:, doc_pii_response:, passport_response:)
# image validation failed
return form_response unless form_response.success?

# doc_pii validation failed
return doc_pii_response if doc_pii_response.present? && !doc_pii_response.success?

return passport_response if passport_response.present? && !passport_response.success?

client_response
end

Expand Down
3 changes: 2 additions & 1 deletion app/forms/idv/doc_pii_form.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ class DocPiiForm
validate :dob_valid?
validate :state_id_or_passport

attr_reader :first_name, :last_name, :dob, :state_id_type, :attention_with_barcode
attr_reader :first_name, :last_name, :dob, :attention_with_barcode,
:jurisdiction, :state_id_number, :state_id_expiration, :state_id_type
alias_method :attention_with_barcode?, :attention_with_barcode

def initialize(pii:, attention_with_barcode: false)
Expand Down
Loading