Skip to content

Commit

Permalink
Merge pull request #11222 from 18F/stages/rc-2024-09-10
Browse files Browse the repository at this point in the history
Deploy RC 413 to Production
  • Loading branch information
mdiarra3 authored Sep 10, 2024
2 parents 97178a2 + 985f922 commit 1f8127a
Show file tree
Hide file tree
Showing 85 changed files with 896 additions and 226 deletions.
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.21.8-18f'
gem 'saml_idp', github: '18F/saml_idp', tag: '0.22.0-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 @@ -35,10 +35,10 @@ GIT

GIT
remote: https://github.com/18F/saml_idp.git
revision: e52d679ab060531e12c19a27357aec4cd9b63546
tag: 0.21.8-18f
revision: 9b9e118e3811df70e4586a4b6585dbc69f928625
tag: 0.22.0-18f
specs:
saml_idp (0.21.8.pre.18f)
saml_idp (0.22.0.pre.18f)
activesupport
builder
faraday
Expand Down
7 changes: 5 additions & 2 deletions app/assets/stylesheets/components/_card.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@
@use '../variables/app' as *;

.card {
@include u-padding(4);
background-color: color('white');
max-width: $container-skinny-width;

& + & {
@include u-margin-top(4);
}

@include at-media('tablet') {
@include u-padding-x(10);
@include u-margin-bottom(8);
border-radius: 5px;
}
}
1 change: 0 additions & 1 deletion app/assets/stylesheets/components/_index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
@forward 'link';
@forward 'header';
@forward 'page-heading';
@forward 'profile-section';
@forward 'personal-key';
@forward 'radio-button';
@forward 'spinner-button';
Expand Down
5 changes: 0 additions & 5 deletions app/assets/stylesheets/components/_profile-section.scss

This file was deleted.

6 changes: 3 additions & 3 deletions app/controllers/idv/agreement_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def show
)

@consent_form = Idv::ConsentForm.new(
idv_consent_given: idv_session.idv_consent_given,
idv_consent_given: idv_session.idv_consent_given?,
)
end

Expand All @@ -27,7 +27,7 @@ def update
skip_to_capture if params[:skip_hybrid_handoff]

@consent_form = Idv::ConsentForm.new(
idv_consent_given: idv_session.idv_consent_given,
idv_consent_given: idv_session.idv_consent_given?,
)
result = @consent_form.submit(consent_form_params)

Expand Down Expand Up @@ -57,7 +57,7 @@ def self.step_info
next_steps: [:hybrid_handoff, :document_capture, :how_to_verify],
preconditions: ->(idv_session:, user:) { idv_session.welcome_visited },
undo_step: ->(idv_session:, user:) do
idv_session.idv_consent_given = nil
idv_session.idv_consent_given_at = nil
idv_session.skip_hybrid_handoff = nil
end,
)
Expand Down
5 changes: 2 additions & 3 deletions app/controllers/idv/cancellations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def cancel_session
if hybrid_session?
cancel_document_capture_session
else
cancel_in_person_enrollment_if_exists
cancel_establishing_in_person_enrollments
idv_session = user_session[:idv]
idv_session&.clear
user_session['idv/in_person'] = {}
Expand Down Expand Up @@ -113,9 +113,8 @@ def session_go_back_path
end
end

def cancel_in_person_enrollment_if_exists
def cancel_establishing_in_person_enrollments
return if !IdentityConfig.store.in_person_proofing_enabled
current_user.pending_in_person_enrollment&.update(status: :cancelled)
UspsInPersonProofing::EnrollmentHelper.
cancel_stale_establishing_enrollments_for_user(current_user)
end
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/idv/document_capture_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ def handle_stored_result

def allow_direct_ipp?
return false unless idv_session.welcome_visited &&
idv_session.idv_consent_given
idv_session.idv_consent_given?
# not allowed when no step param and action:show(get request)
return false if params[:step].blank? || params[:action].to_s != 'show' ||
idv_session.flow_path == 'hybrid'
Expand Down
3 changes: 2 additions & 1 deletion app/controllers/idv/enter_password_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ class EnterPasswordController < ApplicationController
include IdvStepConcern
include StepIndicatorConcern
include VerifyByMailConcern
include IppHelper

before_action :confirm_step_allowed
before_action :confirm_no_profile_yet
Expand Down Expand Up @@ -186,7 +187,7 @@ def handle_request_enroll_exception(err)
enrollment_id: err.enrollment_id,
exception_class: err.class.to_s,
original_exception_class: err.exception_class,
exception_message: err.message,
exception_message: scrub_message(err.message),
reason: 'Request exception',
)
flash[:error] = t('idv.failure.exceptions.internal_error')
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/idv/how_to_verify_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def self.step_info
next_steps: [:hybrid_handoff, :document_capture],
preconditions: ->(idv_session:, user:) do
self.enabled? &&
idv_session.idv_consent_given &&
idv_session.idv_consent_given? &&
idv_session.service_provider&.in_person_proofing_enabled
end,
undo_step: ->(idv_session:, user:) {
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/idv/hybrid_handoff_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def self.step_info
controller: self,
next_steps: [:link_sent, :document_capture],
preconditions: ->(idv_session:, user:) {
idv_session.idv_consent_given &&
idv_session.idv_consent_given? &&
(self.selected_remote(idv_session: idv_session) || # from opt-in screen
# back from ipp doc capture screen
idv_session.skip_doc_auth_from_handoff)
Expand Down
15 changes: 14 additions & 1 deletion app/controllers/idv/in_person/state_id_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -148,11 +148,24 @@ def parsed_dob

def pii
data = pii_from_user
data = data.merge(flow_params) if params.has_key?(:state_id)
if params.has_key?(:identity_doc) || params.has_key?(:state_id)
data = data.merge(flow_params)
end
data.deep_symbolize_keys
end

def flow_params
if params.dig(:identity_doc).present?
# Transform the top-level params key to accept the renamed form
# for autofill handling workaround
params[:state_id] = params.delete(:identity_doc)

# Rename nested id_number to state_id_number
if params[:state_id][:id_number].present?
params[:state_id][:state_id_number] = params[:state_id].delete(:id_number)
end
end

params.require(:state_id).permit(
*Idv::StateIdForm::ATTRIBUTES,
dob: [
Expand Down
6 changes: 4 additions & 2 deletions app/controllers/idv/in_person/usps_locations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class UspsLocationsController < ApplicationController
include Idv::HybridMobile::HybridMobileConcern
include RenderConditionConcern
include UspsInPersonProofing
include IppHelper

check_or_render_not_found -> { InPersonConfig.enabled? }

Expand All @@ -17,6 +18,7 @@ class UspsLocationsController < ApplicationController
rescue_from ActionController::InvalidAuthenticityToken,
Faraday::Error,
StandardError,
Faraday::BadRequestError,
with: :handle_error

# retrieve the list of nearby IPP Post Office locations with a POST request
Expand Down Expand Up @@ -103,9 +105,9 @@ def handle_error(err)
analytics.idv_in_person_locations_request_failure(
api_status_code: Rack::Utils.status_code(remapped_error),
exception_class: err.class,
exception_message: err.message,
exception_message: scrub_message(err.message),
response_body_present: err.respond_to?(:response_body) && err.response_body.present?,
response_body: err.respond_to?(:response_body) && err.response_body,
response_body: err.respond_to?(:response_body) && scrub_body(err.response_body),
response_status_code: err.respond_to?(:response_status) && err.response_status,
)
render json: {}, status: remapped_error
Expand Down
43 changes: 34 additions & 9 deletions app/controllers/socure_webhook_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,35 @@ class SocureWebhookController < ApplicationController
include RenderConditionConcern

skip_before_action :verify_authenticity_token

check_or_render_not_found -> { IdentityConfig.store.socure_webhook_enabled }
before_action :check_token
before_action :check_socure_event

def create
if token_valid?
render json: { message: 'Secret token is valid.' }
else
log_webhook_receipt
render json: { message: 'Secret token is valid.' }
end

private

def check_token
if !token_valid?
render status: :unauthorized, json: { message: 'Invalid secret token.' }
end
end

private
def check_socure_event
if socure_params[:event].blank?
render status: :bad_request, json: { message: 'Invalid event.' }
end
end

def token_valid?
authorization_header = request.headers['Authorization']&.split&.last

return false if authorization_header.nil?

verify_current_key(authorization_header: authorization_header) ||
verify_queue(authorization_header: authorization_header)
authorization_header.present? &&
(verify_current_key(authorization_header: authorization_header) ||
verify_queue(authorization_header: authorization_header))
end

def verify_current_key(authorization_header:)
Expand All @@ -41,4 +50,20 @@ def verify_queue(authorization_header:)
)
end
end

def log_webhook_receipt
event = socure_params[:event]

analytics.idv_doc_auth_socure_webhook_received(
created_at: event[:created],
customer_user_id: event[:customerUserId],
event_type: event[:eventType],
reference_id: event[:referenceId],
user_id: event[:customerUserId],
)
end

def socure_params
params.permit(event: [:created, :customerUserId, :eventType, :referenceId])
end
end
8 changes: 8 additions & 0 deletions app/controllers/users/sessions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class SessionsController < Devise::SessionsController
include ForcedReauthenticationConcern
include NewDeviceConcern
include AbTestingConcern
include RecaptchaConcern

rescue_from ActionController::InvalidAuthenticityToken, with: :redirect_to_signin

Expand All @@ -18,6 +19,9 @@ class SessionsController < Devise::SessionsController
before_action :check_user_needs_redirect, only: [:new]
before_action :apply_secure_headers_override, only: [:new, :create]
before_action :clear_session_bad_password_count_if_window_expired, only: [:create]
before_action :allow_csp_recaptcha_src, if: :recaptcha_enabled?

after_action :add_recaptcha_resource_hints, if: :recaptcha_enabled?

def new
override_csp_for_google_analytics
Expand Down Expand Up @@ -112,6 +116,10 @@ def recaptcha_form
)
end

def recaptcha_enabled?
FeatureManagement.sign_in_recaptcha_enabled?
end

def captcha_validation_performed?
!recaptcha_form.exempt?
end
Expand Down
14 changes: 12 additions & 2 deletions app/forms/idv/api_image_upload_form.rb
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,15 @@ def submit_attempts
rate_limiter.attempts if document_capture_session
end

def processed_selfie_attempts_data
return {} if document_capture_session.nil? || !liveness_checking_required

captured_result = document_capture_session&.load_result
processed_selfie_count = selfie_image_fingerprint ? 1 : 0
past_selfie_count = (captured_result&.failed_selfie_image_fingerprints || []).length
{ selfie_attempts: past_selfie_count + processed_selfie_count }
end

def determine_response(form_response:, client_response:, doc_pii_response:)
# image validation failed
return form_response unless form_response.success?
Expand Down Expand Up @@ -363,14 +372,15 @@ def update_analytics(client_response:, vendor_request_time_in_ms:)
zip_code: zip_code,
issue_year: issue_year,
).except(:classification_info).
merge(acuant_sdk_upgrade_ab_test_data),
merge(acuant_sdk_upgrade_ab_test_data).
merge(processed_selfie_attempts_data),
)
end

def acuant_sdk_upgrade_ab_test_data
{
acuant_sdk_upgrade_ab_test_bucket:,
}.compact
}
end

def acuant_sdk_captured?
Expand Down
2 changes: 1 addition & 1 deletion app/forms/webauthn_setup_form.rb
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,6 @@ def extra_analytics_attributes
authenticator_data_flags: authenticator_data_flags,
unknown_transports: invalid_transports.presence,
aaguid: aaguid,
}.compact
}
end
end
2 changes: 1 addition & 1 deletion app/forms/webauthn_verification_form.rb
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,6 @@ def extra_analytics_attributes
webauthn_configuration_id: webauthn_configuration&.id,
frontend_error: webauthn_error.presence,
webauthn_aaguid: webauthn_configuration&.aaguid,
}.compact
}
end
end
15 changes: 15 additions & 0 deletions app/helpers/ipp_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# frozen_string_literal: true

module IppHelper
def scrub_message(message)
message.gsub(/sponsorID \d+/i, 'sponsorID [FILTERED]')
end

def scrub_body(body)
return nil if body.nil?

body = body.with_indifferent_access
body[:responseMessage] = scrub_message(body[:responseMessage])
body
end
end
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
class ValidatedFieldElement extends HTMLElement {
errorStrings: Partial<ValidityState> = {};

input: HTMLInputElement | null;

inputWrapper: HTMLElement | null;
Expand All @@ -11,18 +9,19 @@ class ValidatedFieldElement extends HTMLElement {
this.input = this.querySelector('.validated-field__input');
this.inputWrapper = this.querySelector('.validated-field__input-wrapper');
this.errorMessage = this.ownerDocument.getElementById(this.errorId);
try {
Object.assign(
this.errorStrings,
JSON.parse(this.querySelector('.validated-field__error-strings')?.textContent || ''),
);
} catch {}

this.input?.addEventListener('input', () => this.setErrorMessage());
this.input?.addEventListener('input', () => this.setInputIsValid(true));
this.input?.addEventListener('invalid', (event) => this.toggleErrorMessage(event));
}

get errorStrings(): Partial<ValidityState> {
try {
return JSON.parse(this.querySelector('.validated-field__error-strings')?.textContent || '');
} catch {
return {};
}
}

get errorId(): string {
return this.getAttribute('error-id')!;
}
Expand Down
Loading

0 comments on commit 1f8127a

Please sign in to comment.