Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
8ff746f
Add name suffix to TrueID response fixture (#11534)
jmhooper Nov 20, 2024
108f2ae
Fix the whitespace in the TrueID success response fixtures (#11535)
jmhooper Nov 20, 2024
d31f490
Dmm/clean up config (#11533)
Sgtpluck Nov 20, 2024
0a24160
LG-14366 Store dynamically-generated proofing components on Profile (…
jmhooper Nov 20, 2024
362dc90
LG-15125: Wait for Socure result - hybrid flow (#11530)
solipet Nov 20, 2024
56ba291
Remove allowed_extra_analytics (#11536)
aduth Nov 21, 2024
656c479
Remove unused allowed_extra_analytics (#11537)
aduth Nov 21, 2024
6dc9aa5
Revert logging whether password matches current for password reset ev…
aduth Nov 21, 2024
bc88339
LG-15016: Socure document capture feature specs starter (#11529)
amirbey Nov 21, 2024
aa2c2db
Revert "LG-14828 Remove deprecated state ID step routes (#11510)" (#1…
aduth Nov 21, 2024
c0eaa1d
Remove proofer_mock_fallback, erm, fallback (#11516)
matthinz Nov 22, 2024
570d0c1
LG-14725: Identity resolution via Socure (#11523)
matthinz Nov 22, 2024
94e98d7
Document usage of Lookbook for ViewComponents (#11540)
aduth Nov 25, 2024
f53a5fd
Upgrade DAP to v8.4 release (#11539)
aduth Nov 25, 2024
0ad50f9
Add uncapped preload headers for style, script assets (#11504)
aduth Nov 25, 2024
0aa1128
Update Data Request script to compute requesting issuer and have conf…
Nov 25, 2024
d1f9c01
Log Face/Touch setup A/B test from session value (#11549)
aduth Nov 25, 2024
143ed96
Do not return User UUID in requesting_issuer_uuid when generating use…
Nov 25, 2024
c45cac1
LG-15171 Fixes redirect for PUT (#11545)
jennyverdeyen Nov 25, 2024
5693220
Add analytics tracking for signature algorithm errors (#11552)
Sgtpluck Nov 25, 2024
80e393f
LG-15119 Update MKMR to split verified users by facial matching (#11557)
ThatSpaceGuy Nov 25, 2024
3f0fd8c
LG-15098: Run the Socure DocV result job in it's own queue. (#11548)
solipet Nov 25, 2024
fba9f9b
Log requesting signing and certificate serial in SAML Auth Request ev…
Nov 26, 2024
a5dcf58
Merge remote-tracking branch 'origin/stages/prod' into stages/rc-2024…
amirbey Nov 26, 2024
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
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ gem 'rqrcode'
gem 'ruby-progressbar'
gem 'ruby-saml'
gem 'safe_target_blank', '>= 1.0.2'
gem 'saml_idp', github: '18F/saml_idp', tag: '0.23.0-18f'
gem 'saml_idp', github: '18F/saml_idp', tag: '0.23.3-18f'
gem 'scrypt'
gem 'simple_form', '>= 5.0.2'
gem 'stringex', require: false
Expand Down
6 changes: 3 additions & 3 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ GIT

GIT
remote: https://github.com/18F/saml_idp.git
revision: 23b69117593e9b9217910af1dd627febd8d18cf4
tag: 0.23.0-18f
revision: 752085a6f88cd3ce75ecc7a64afe064a0e4f9e35
tag: 0.23.3-18f
specs:
saml_idp (0.23.0.pre.18f)
saml_idp (0.23.3.pre.18f)
activesupport
builder
faraday
Expand Down
8 changes: 7 additions & 1 deletion app/controllers/idv/enter_password_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,13 @@ def confirm_current_password
def init_profile
idv_session.create_profile_from_applicant_with_password(
password,
resolved_authn_context_result.enhanced_ipp?,
is_enhanced_ipp: resolved_authn_context_result.enhanced_ipp?,
proofing_components: ProofingComponents.new(
user: current_user,
idv_session:,
session:,
user_session:,
).to_h,
)
if idv_session.verify_by_mail?
current_user.send_email_to_all_addresses(:verify_by_mail_letter_requested)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@ module Idv
module HybridMobile
module Socure
class DocumentCaptureController < ApplicationController
include Idv::AvailabilityConcern
include AvailabilityConcern
include DocumentCaptureConcern
include Idv::HybridMobile::HybridMobileConcern
include RenderConditionConcern
include DocumentCaptureConcern

check_or_render_not_found -> { IdentityConfig.store.socure_docv_enabled }
before_action :check_valid_document_capture_session, except: [:update]
Expand Down Expand Up @@ -50,17 +49,64 @@ def show
end

def update
return if wait_for_result?

result = handle_stored_result(
user: document_capture_session.user,
store_in_session: false,
)
# TODO: new analytics event?
analytics.idv_doc_auth_document_capture_submitted(
**result.to_h.merge(analytics_arguments),
)

if result.success?
redirect_to idv_hybrid_mobile_capture_complete_url
else
redirect_to idv_hybrid_mobile_socure_document_capture_url
end
end

private

def wait_for_result?
return false if stored_result.present?

# If the stored_result is nil, the job fetching the results has not completed.
analytics.idv_doc_auth_document_capture_polling_wait_visited(**analytics_arguments)
if wait_timed_out?
# flash[:error] = I18n.t('errors.doc_auth.polling_timeout')
# TODO: redirect to try again page LG-14873/14952/15059
render plain: 'Technical difficulties!!!', status: :ok
else
@refresh_interval =
IdentityConfig.store.doc_auth_socure_wait_polling_refresh_max_seconds
render 'idv/socure/document_capture/wait'
end

true
end

def wait_timed_out?
if session[:socure_docv_wait_polling_started_at].nil?
session[:socure_docv_wait_polling_started_at] = Time.zone.now.to_s
return false
end
start = DateTime.parse(session[:socure_docv_wait_polling_started_at])
timeout_period =
IdentityConfig.store.doc_auth_socure_wait_polling_timeout_minutes.minutes || 2.minutes
start + timeout_period < Time.zone.now
end

def analytics_arguments
{
flow_path: 'hybrid',
step: 'socure_document_capture',
analytics_id: 'Doc Auth',
liveness_checking_required: false,
selfie_check_required: false,
}
end
end
end
end
Expand Down
38 changes: 21 additions & 17 deletions app/controllers/idv/socure/document_capture_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,27 +62,13 @@ def show
end

def update
return if wait_for_result?

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

# If the stored_result is nil, the job fetching the results has not completed.
if stored_result.nil?
analytics.idv_doc_auth_document_capture_polling_wait_visited(**analytics_arguments)
if wait_timed_out?
# flash[:error] = I18n.t('errors.doc_auth.polling_timeout')
# TODO: redirect to try again page LG-14873/14952/15059
render plain: 'Technical difficulties!!!', status: :ok
else
@refresh_interval =
IdentityConfig.store.doc_auth_socure_wait_polling_refresh_max_seconds
render 'idv/socure/document_capture/wait'
end

return
end

result = handle_stored_result
# TODO: new analytics event?
analytics.idv_doc_auth_document_capture_submitted(**result.to_h.merge(analytics_arguments))
Expand Down Expand Up @@ -121,14 +107,32 @@ def self.step_info

private

def wait_for_result?
return false if stored_result.present?

# If the stored_result is nil, the job fetching the results has not completed.
analytics.idv_doc_auth_document_capture_polling_wait_visited(**analytics_arguments)
if wait_timed_out?
# flash[:error] = I18n.t('errors.doc_auth.polling_timeout')
# TODO: redirect to try again page LG-14873/14952/15059
render plain: 'Technical difficulties!!!', status: :ok
else
@refresh_interval =
IdentityConfig.store.doc_auth_socure_wait_polling_refresh_max_seconds
render 'idv/socure/document_capture/wait'
end

true
end

def wait_timed_out?
if idv_session.socure_docv_wait_polling_started_at.nil?
idv_session.socure_docv_wait_polling_started_at = Time.zone.now.to_s
return false
end
start = DateTime.parse(idv_session.socure_docv_wait_polling_started_at)
timeout_period =
IdentityConfig.store.doc_auth_socure_wait_polling_timeout_minutes.minutes || 5.minutes
IdentityConfig.store.doc_auth_socure_wait_polling_timeout_minutes.minutes || 2.minutes
start + timeout_period < Time.zone.now
end

Expand Down
24 changes: 24 additions & 0 deletions app/controllers/saml_idp_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,13 @@ def capture_analytics

if result.success? && saml_request.signed?
analytics_payload[:cert_error_details] = saml_request.cert_errors

# analytics to determine if turning on SHA256 validation will break
# existing partners
if certs_different?
analytics_payload[:certs_different] = true
analytics_payload[:sha256_matching_cert] = sha256_alg_matching_cert_serial
end
end

analytics.saml_auth(**analytics_payload)
Expand All @@ -147,6 +154,21 @@ def matching_cert_serial
nil
end

def sha256_alg_matching_cert
# if sha256_alg_matching_cert is nil, fallback to the "first" cert
saml_request.sha256_validation_matching_cert ||
saml_request_service_provider&.ssl_certs&.first
rescue SamlIdp::XMLSecurity::SignedDocument::ValidationError
end

def sha256_alg_matching_cert_serial
sha256_alg_matching_cert&.serial&.to_s
end

def certs_different?
encryption_cert != sha256_alg_matching_cert
end

def log_external_saml_auth_request
return unless external_saml_request?

Expand All @@ -158,6 +180,8 @@ def log_external_saml_auth_request
force_authn: saml_request&.force_authn?,
final_auth_request: sp_session[:final_auth_request],
service_provider: saml_request&.issuer,
request_signed: saml_request.signed?,
matching_cert_serial:,
unknown_authn_contexts:,
user_fully_authenticated: user_fully_authenticated?,
)
Expand Down
10 changes: 1 addition & 9 deletions app/controllers/users/reset_passwords_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
module Users
class ResetPasswordsController < Devise::PasswordsController
include AuthorizationCountConcern
include AbTestingConcern

before_action :store_sp_metadata_in_session, only: [:edit]
before_action :store_token_in_session, only: [:edit]

Expand Down Expand Up @@ -44,13 +42,7 @@ def edit

def update
self.resource = user_matching_token(user_params[:reset_password_token])
@reset_password_form = ResetPasswordForm.new(
user: resource,
log_password_matches_existing: ab_test_bucket(
:LOG_PASSWORD_RESET_MATCHES_EXISTING,
user: resource,
) == :log,
)
@reset_password_form = ResetPasswordForm.new(user: resource)

result = @reset_password_form.submit(user_params)

Expand Down
10 changes: 10 additions & 0 deletions app/controllers/users/webauthn_platform_recommended_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,22 @@ def new

def create
analytics.webauthn_platform_recommended_submitted(opted_to_add: opted_to_add?)
store_webauthn_platform_recommended_in_session if opted_to_add?
current_user.update(webauthn_platform_recommended_dismissed_at: Time.zone.now)
redirect_to dismiss_redirect_path
end

private

def store_webauthn_platform_recommended_in_session
user_session[:webauthn_platform_recommended] =
if in_account_creation_flow?
:account_creation
else
:authentication
end
end

def opted_to_add?
params[:add_method].present?
end
Expand Down
1 change: 1 addition & 0 deletions app/controllers/users/webauthn_setup_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ def process_valid_webauthn(form)
def analytics_properties
{
in_account_creation_flow: user_session[:in_account_creation_flow] || false,
webauthn_platform_recommended: user_session[:webauthn_platform_recommended],
attempts: mfa_attempts_count,
}
end
Expand Down
8 changes: 1 addition & 7 deletions app/forms/reset_password_form.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,11 @@ class ResetPasswordForm
include FormPasswordValidator

attr_accessor :reset_password_token
private attr_reader :log_password_matches_existing
alias_method :log_password_matches_existing?, :log_password_matches_existing

validate :valid_token

def initialize(user:, log_password_matches_existing: false)
def initialize(user:)
@user = user
@log_password_matches_existing = log_password_matches_existing
@reset_password_token = @user.reset_password_token
@validate_confirmation = true
@active_profile = user.active_profile
Expand Down Expand Up @@ -50,8 +47,6 @@ def handle_valid_password
end

def update_user
@password_matches_existing = user.valid_password?(password) if log_password_matches_existing?

attributes = { password: password }

ActiveRecord::Base.transaction do
Expand Down Expand Up @@ -92,7 +87,6 @@ def extra_analytics_attributes
{
user_id: user.uuid,
profile_deactivated: active_profile.present?,
password_matches_existing: @password_matches_existing,
pending_profile_invalidated: pending_profile.present?,
pending_profile_pending_reasons: (pending_profile&.pending_reasons || [])&.join(','),
}
Expand Down
22 changes: 17 additions & 5 deletions app/helpers/script_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,26 @@ def render_javascript_pack_once_tags(...)
javascript_packs_tag_once(...)
return if @scripts.blank?
concat javascript_assets_tag
crossorigin = local_crossorigin_sources?.presence
@scripts.each do |name, (url_params, attributes)|
asset_sources.get_sources(name).each do |source|
concat javascript_include_tag(
UriService.add_params(source, url_params),
integrity = asset_sources.get_integrity(source)

if attributes[:preload_links_header] != false
AssetPreloadLinker.append(
headers: response.headers,
as: :script,
url: source,
crossorigin:,
integrity:,
)
end

concat tag.script(
src: UriService.add_params(source, url_params),
**attributes,
crossorigin: local_crossorigin_sources? ? true : nil,
integrity: asset_sources.get_integrity(source),
nopush: false,
crossorigin:,
integrity:,
)
end
end
Expand Down
8 changes: 7 additions & 1 deletion app/helpers/stylesheet_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,13 @@ def stylesheet_tag_once(*names)
def render_stylesheet_once_tags(*names)
stylesheet_tag_once(*names) if names.present?
return if @stylesheets.blank?
safe_join(@stylesheets.map { |stylesheet| stylesheet_link_tag(stylesheet, nopush: false) })
safe_join(
@stylesheets.map do |stylesheet|
url = stylesheet_path(stylesheet)
AssetPreloadLinker.append(headers: response.headers, as: :style, url:)
tag.link(rel: :stylesheet, href: url)
end,
)
end
end
# rubocop:enable Rails/HelperInstanceVariable
2 changes: 1 addition & 1 deletion app/javascript/packages/analytics/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
DAP_SHA ?= 7c14bb3
DAP_SHA ?= eebc4d1

digital-analytics-program.js: digital-analytics-program-$(DAP_SHA).js digital-analytics-program.patch
patch -p1 $^ --output $@
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,2 @@
73a74
> GA4Object.defer = true;
785d785
< var piiRegex = [];
900c900
< piiRegex.forEach(function (pii) {
---
> window.piiRegex.forEach(function (pii) {
87a88
> GA4Object.defer = true;
2 changes: 1 addition & 1 deletion app/jobs/resolution_proofing_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def perform(

if IdentityConfig.store.idv_socure_shadow_mode_enabled
SocureShadowModeProofingJob.perform_later(
document_capture_session_result_id: document_capture_session.result_id,
document_capture_session_result_id: document_capture_session&.result_id,
encrypted_arguments:,
service_provider_issuer:,
user_email: user_email_for_proofing(user),
Expand Down
2 changes: 1 addition & 1 deletion app/jobs/socure_docv_results_job.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

class SocureDocvResultsJob < ApplicationJob
queue_as :default
queue_as :high_socure_docv

attr_reader :document_capture_session_uuid

Expand Down
Loading