diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 82ea5f102c3..2083b53f37d 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -469,7 +469,7 @@ trigger_devops:
- >-
helm upgrade --install --namespace review-apps
--debug
- --set env="reviewapps"
+ --set env="reviewapps-$CI_ENVIRONMENT_SLUG"
--set idp.image.repository="${ECR_REGISTRY}/identity-idp/review"
--set idp.image.tag="${CI_COMMIT_SHA}"
--set worker.image.repository="${ECR_REGISTRY}/identity-idp/review"
@@ -490,7 +490,7 @@ trigger_devops:
--set-json dashboard.ingress.hosts="[{\"host\": \"$CI_ENVIRONMENT_SLUG-review-app-dashboard.review-app.identitysandbox.gov\", \"paths\": [{\"path\": \"/\", \"pathType\": \"Prefix\"}]}]"
$CI_ENVIRONMENT_SLUG ./identity-idp-helm-chart
- echo "DNS may take a while to propagate, so be patient if it doesn't show up right away"
- - echo "To access the rails console, first run 'aws-vault exec sandbox-power -- aws eks update-kubeconfig --name review_app'"
+ - echo "To access the rails console, first run 'aws-vault exec sandbox-power -- aws eks update-kubeconfig --name reviewapps'"
- echo "Then run aws-vault exec sandbox-power -- kubectl exec -it service/$CI_ENVIRONMENT_SLUG-login-chart-idp -n review-apps -- /app/bin/rails console"
- echo "Address of IDP review app:"
- echo https://$CI_ENVIRONMENT_SLUG.review-app.identitysandbox.gov
diff --git a/Gemfile b/Gemfile
index 4bfc01fa764..0a851079286 100644
--- a/Gemfile
+++ b/Gemfile
@@ -68,7 +68,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.20.2-18f'
+gem 'saml_idp', github: '18F/saml_idp', tag: '0.21.0-18f'
gem 'scrypt'
gem 'simple_form', '>= 5.0.2'
gem 'stringex', require: false
diff --git a/Gemfile.lock b/Gemfile.lock
index 2e22b77122b..7f219b5e301 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -35,10 +35,10 @@ GIT
GIT
remote: https://github.com/18F/saml_idp.git
- revision: dd8643b16c8214f7b791763538180d043af7ef65
- tag: 0.20.2-18f
+ revision: 33275d69f7609e448942d6e3ce5c27779920995f
+ tag: 0.21.0-18f
specs:
- saml_idp (0.20.2.pre.18f)
+ saml_idp (0.21.0.pre.18f)
activesupport
builder
faraday
diff --git a/Makefile b/Makefile
index 5fa605ec554..6137cb4b5d5 100644
--- a/Makefile
+++ b/Makefile
@@ -26,6 +26,7 @@ ARTIFACT_DESTINATION_FILE ?= ./tmp/idp.tar.gz
lint_analytics_events_sorted \
lint_country_dialing_codes \
lint_erb \
+ lint_font_glyphs \
lint_lockfiles \
lint_new_typescript_files \
lint_optimized_assets \
@@ -87,6 +88,8 @@ endif
# Other
@echo "--- lint yaml ---"
make lint_yaml
+ @echo "--- lint font glyphs ---"
+ make lint_font_glyphs
@echo "--- lint Yarn workspaces ---"
make lint_yarn_workspaces
@echo "--- lint new TypeScript files ---"
@@ -110,6 +113,15 @@ lint_erb: ## Lints ERB files
lint_yaml: normalize_yaml ## Lints YAML files
(! git diff --name-only | grep "^config/.*\.yml$$") || (echo "Error: Run 'make normalize_yaml' to normalize YAML"; exit 1)
+lint_font_glyphs: ## Lints to validate content glyphs match expectations from fonts
+ scripts/yaml_characters \
+ --exclude-locale=zh \
+ --exclude-gem-path=faker \
+ --exclude-gem-path=good_job \
+ --exclude-gem-path=i18n-tasks \
+ > app/assets/fonts/glyphs.txt
+ (! git diff --name-only | grep "glyphs\.txt$$") || (echo "Error: New character data found. Follow 'Fonts' instructions in 'docs/frontend.md' to regenerate fonts."; exit 1)
+
lint_yarn_workspaces: ## Lints Yarn workspace packages
scripts/validate-workspaces.mjs
@@ -121,7 +133,7 @@ lint_asset_bundle_size: ## Lints JavaScript and CSS compiled bundle size
@# budget and accept the fact that this will force end-users to endure longer load times, you
@# should set the new budget to within a few thousand bytes of the production-compiled size.
find app/assets/builds/application.css -size -185000c | grep .
- find public/packs/js/application-*.digested.js -size -5000c | grep .
+ find public/packs/application-*.digested.js -size -5000c | grep .
lint_migrations:
scripts/migration_check
diff --git a/app/assets/fonts/glyphs.txt b/app/assets/fonts/glyphs.txt
new file mode 100644
index 00000000000..4c552993112
--- /dev/null
+++ b/app/assets/fonts/glyphs.txt
@@ -0,0 +1 @@
+ !"#$%&'(),-./0123456789:;>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~ «»¿ÀÁÈÉÊÎÓÚàáâãçèéêëíîïñóôùúû ‑—‘’“”…‹中体文简
diff --git a/app/assets/fonts/public-sans/PublicSans-Black.woff b/app/assets/fonts/public-sans/PublicSans-Black.woff
deleted file mode 100644
index 8174446d892..00000000000
Binary files a/app/assets/fonts/public-sans/PublicSans-Black.woff and /dev/null differ
diff --git a/app/assets/fonts/public-sans/PublicSans-Black.woff2 b/app/assets/fonts/public-sans/PublicSans-Black.woff2
index 656549ff192..28de4cbb742 100644
Binary files a/app/assets/fonts/public-sans/PublicSans-Black.woff2 and b/app/assets/fonts/public-sans/PublicSans-Black.woff2 differ
diff --git a/app/assets/fonts/public-sans/PublicSans-BlackItalic.woff b/app/assets/fonts/public-sans/PublicSans-BlackItalic.woff
deleted file mode 100644
index 4b3f2495856..00000000000
Binary files a/app/assets/fonts/public-sans/PublicSans-BlackItalic.woff and /dev/null differ
diff --git a/app/assets/fonts/public-sans/PublicSans-BlackItalic.woff2 b/app/assets/fonts/public-sans/PublicSans-BlackItalic.woff2
index a77821ca359..891b65c5319 100644
Binary files a/app/assets/fonts/public-sans/PublicSans-BlackItalic.woff2 and b/app/assets/fonts/public-sans/PublicSans-BlackItalic.woff2 differ
diff --git a/app/assets/fonts/public-sans/PublicSans-Bold.woff b/app/assets/fonts/public-sans/PublicSans-Bold.woff
deleted file mode 100644
index a330a13dcf0..00000000000
Binary files a/app/assets/fonts/public-sans/PublicSans-Bold.woff and /dev/null differ
diff --git a/app/assets/fonts/public-sans/PublicSans-Bold.woff2 b/app/assets/fonts/public-sans/PublicSans-Bold.woff2
index eaffd02816e..3fad30fba01 100644
Binary files a/app/assets/fonts/public-sans/PublicSans-Bold.woff2 and b/app/assets/fonts/public-sans/PublicSans-Bold.woff2 differ
diff --git a/app/assets/fonts/public-sans/PublicSans-BoldItalic.woff b/app/assets/fonts/public-sans/PublicSans-BoldItalic.woff
deleted file mode 100644
index d03f7ca2295..00000000000
Binary files a/app/assets/fonts/public-sans/PublicSans-BoldItalic.woff and /dev/null differ
diff --git a/app/assets/fonts/public-sans/PublicSans-BoldItalic.woff2 b/app/assets/fonts/public-sans/PublicSans-BoldItalic.woff2
index bdd712d81eb..172dd572175 100644
Binary files a/app/assets/fonts/public-sans/PublicSans-BoldItalic.woff2 and b/app/assets/fonts/public-sans/PublicSans-BoldItalic.woff2 differ
diff --git a/app/assets/fonts/public-sans/PublicSans-ExtraBold.woff b/app/assets/fonts/public-sans/PublicSans-ExtraBold.woff
deleted file mode 100644
index 33ceeb2fa59..00000000000
Binary files a/app/assets/fonts/public-sans/PublicSans-ExtraBold.woff and /dev/null differ
diff --git a/app/assets/fonts/public-sans/PublicSans-ExtraBold.woff2 b/app/assets/fonts/public-sans/PublicSans-ExtraBold.woff2
index 0caaa499cc2..91d6ecbee2b 100644
Binary files a/app/assets/fonts/public-sans/PublicSans-ExtraBold.woff2 and b/app/assets/fonts/public-sans/PublicSans-ExtraBold.woff2 differ
diff --git a/app/assets/fonts/public-sans/PublicSans-ExtraBoldItalic.woff b/app/assets/fonts/public-sans/PublicSans-ExtraBoldItalic.woff
deleted file mode 100644
index a89787fd384..00000000000
Binary files a/app/assets/fonts/public-sans/PublicSans-ExtraBoldItalic.woff and /dev/null differ
diff --git a/app/assets/fonts/public-sans/PublicSans-ExtraBoldItalic.woff2 b/app/assets/fonts/public-sans/PublicSans-ExtraBoldItalic.woff2
index 774fe32b0a3..4bcd956a1b6 100644
Binary files a/app/assets/fonts/public-sans/PublicSans-ExtraBoldItalic.woff2 and b/app/assets/fonts/public-sans/PublicSans-ExtraBoldItalic.woff2 differ
diff --git a/app/assets/fonts/public-sans/PublicSans-ExtraLight.woff b/app/assets/fonts/public-sans/PublicSans-ExtraLight.woff
deleted file mode 100644
index 7ae600def7e..00000000000
Binary files a/app/assets/fonts/public-sans/PublicSans-ExtraLight.woff and /dev/null differ
diff --git a/app/assets/fonts/public-sans/PublicSans-ExtraLight.woff2 b/app/assets/fonts/public-sans/PublicSans-ExtraLight.woff2
index 219329aba5b..42af48d4b86 100644
Binary files a/app/assets/fonts/public-sans/PublicSans-ExtraLight.woff2 and b/app/assets/fonts/public-sans/PublicSans-ExtraLight.woff2 differ
diff --git a/app/assets/fonts/public-sans/PublicSans-ExtraLightItalic.woff b/app/assets/fonts/public-sans/PublicSans-ExtraLightItalic.woff
deleted file mode 100644
index 30b9103786e..00000000000
Binary files a/app/assets/fonts/public-sans/PublicSans-ExtraLightItalic.woff and /dev/null differ
diff --git a/app/assets/fonts/public-sans/PublicSans-ExtraLightItalic.woff2 b/app/assets/fonts/public-sans/PublicSans-ExtraLightItalic.woff2
index f0e21c92195..9321da5e3f8 100644
Binary files a/app/assets/fonts/public-sans/PublicSans-ExtraLightItalic.woff2 and b/app/assets/fonts/public-sans/PublicSans-ExtraLightItalic.woff2 differ
diff --git a/app/assets/fonts/public-sans/PublicSans-Italic.woff b/app/assets/fonts/public-sans/PublicSans-Italic.woff
deleted file mode 100644
index 319cb1e8939..00000000000
Binary files a/app/assets/fonts/public-sans/PublicSans-Italic.woff and /dev/null differ
diff --git a/app/assets/fonts/public-sans/PublicSans-Italic.woff2 b/app/assets/fonts/public-sans/PublicSans-Italic.woff2
index a96fa977705..d1bb5d63b8e 100644
Binary files a/app/assets/fonts/public-sans/PublicSans-Italic.woff2 and b/app/assets/fonts/public-sans/PublicSans-Italic.woff2 differ
diff --git a/app/assets/fonts/public-sans/PublicSans-Light.woff b/app/assets/fonts/public-sans/PublicSans-Light.woff
deleted file mode 100644
index 740c94d3387..00000000000
Binary files a/app/assets/fonts/public-sans/PublicSans-Light.woff and /dev/null differ
diff --git a/app/assets/fonts/public-sans/PublicSans-Light.woff2 b/app/assets/fonts/public-sans/PublicSans-Light.woff2
index 87fc6df1e36..5ded7cd94f4 100644
Binary files a/app/assets/fonts/public-sans/PublicSans-Light.woff2 and b/app/assets/fonts/public-sans/PublicSans-Light.woff2 differ
diff --git a/app/assets/fonts/public-sans/PublicSans-LightItalic.woff b/app/assets/fonts/public-sans/PublicSans-LightItalic.woff
deleted file mode 100644
index 9172ccc83a8..00000000000
Binary files a/app/assets/fonts/public-sans/PublicSans-LightItalic.woff and /dev/null differ
diff --git a/app/assets/fonts/public-sans/PublicSans-LightItalic.woff2 b/app/assets/fonts/public-sans/PublicSans-LightItalic.woff2
index bc9b5f7edd7..263a8a0e884 100644
Binary files a/app/assets/fonts/public-sans/PublicSans-LightItalic.woff2 and b/app/assets/fonts/public-sans/PublicSans-LightItalic.woff2 differ
diff --git a/app/assets/fonts/public-sans/PublicSans-Medium.woff b/app/assets/fonts/public-sans/PublicSans-Medium.woff
deleted file mode 100644
index 47a26564c40..00000000000
Binary files a/app/assets/fonts/public-sans/PublicSans-Medium.woff and /dev/null differ
diff --git a/app/assets/fonts/public-sans/PublicSans-Medium.woff2 b/app/assets/fonts/public-sans/PublicSans-Medium.woff2
index 5896b823bdf..907a110e323 100644
Binary files a/app/assets/fonts/public-sans/PublicSans-Medium.woff2 and b/app/assets/fonts/public-sans/PublicSans-Medium.woff2 differ
diff --git a/app/assets/fonts/public-sans/PublicSans-MediumItalic.woff b/app/assets/fonts/public-sans/PublicSans-MediumItalic.woff
deleted file mode 100644
index d0eaa44d398..00000000000
Binary files a/app/assets/fonts/public-sans/PublicSans-MediumItalic.woff and /dev/null differ
diff --git a/app/assets/fonts/public-sans/PublicSans-MediumItalic.woff2 b/app/assets/fonts/public-sans/PublicSans-MediumItalic.woff2
index 0314b97c16e..ef248d4ea6e 100644
Binary files a/app/assets/fonts/public-sans/PublicSans-MediumItalic.woff2 and b/app/assets/fonts/public-sans/PublicSans-MediumItalic.woff2 differ
diff --git a/app/assets/fonts/public-sans/PublicSans-Regular.woff b/app/assets/fonts/public-sans/PublicSans-Regular.woff
deleted file mode 100644
index 8c1da26dbe4..00000000000
Binary files a/app/assets/fonts/public-sans/PublicSans-Regular.woff and /dev/null differ
diff --git a/app/assets/fonts/public-sans/PublicSans-Regular.woff2 b/app/assets/fonts/public-sans/PublicSans-Regular.woff2
index 5f5fcd86111..f787a12e540 100644
Binary files a/app/assets/fonts/public-sans/PublicSans-Regular.woff2 and b/app/assets/fonts/public-sans/PublicSans-Regular.woff2 differ
diff --git a/app/assets/fonts/public-sans/PublicSans-SemiBold.woff b/app/assets/fonts/public-sans/PublicSans-SemiBold.woff
deleted file mode 100644
index 7c530b68836..00000000000
Binary files a/app/assets/fonts/public-sans/PublicSans-SemiBold.woff and /dev/null differ
diff --git a/app/assets/fonts/public-sans/PublicSans-SemiBold.woff2 b/app/assets/fonts/public-sans/PublicSans-SemiBold.woff2
index 14e63ab7528..260aeac6556 100644
Binary files a/app/assets/fonts/public-sans/PublicSans-SemiBold.woff2 and b/app/assets/fonts/public-sans/PublicSans-SemiBold.woff2 differ
diff --git a/app/assets/fonts/public-sans/PublicSans-SemiBoldItalic.woff b/app/assets/fonts/public-sans/PublicSans-SemiBoldItalic.woff
deleted file mode 100644
index ea23cad8b31..00000000000
Binary files a/app/assets/fonts/public-sans/PublicSans-SemiBoldItalic.woff and /dev/null differ
diff --git a/app/assets/fonts/public-sans/PublicSans-SemiBoldItalic.woff2 b/app/assets/fonts/public-sans/PublicSans-SemiBoldItalic.woff2
index 77447b4feb7..b14cc0eaa03 100644
Binary files a/app/assets/fonts/public-sans/PublicSans-SemiBoldItalic.woff2 and b/app/assets/fonts/public-sans/PublicSans-SemiBoldItalic.woff2 differ
diff --git a/app/assets/fonts/public-sans/PublicSans-Thin.woff b/app/assets/fonts/public-sans/PublicSans-Thin.woff
deleted file mode 100644
index 74d7727bd67..00000000000
Binary files a/app/assets/fonts/public-sans/PublicSans-Thin.woff and /dev/null differ
diff --git a/app/assets/fonts/public-sans/PublicSans-Thin.woff2 b/app/assets/fonts/public-sans/PublicSans-Thin.woff2
index bdc7449f203..9587c72b5d7 100644
Binary files a/app/assets/fonts/public-sans/PublicSans-Thin.woff2 and b/app/assets/fonts/public-sans/PublicSans-Thin.woff2 differ
diff --git a/app/assets/fonts/public-sans/PublicSans-ThinItalic.woff b/app/assets/fonts/public-sans/PublicSans-ThinItalic.woff
deleted file mode 100644
index 04dbf4147a6..00000000000
Binary files a/app/assets/fonts/public-sans/PublicSans-ThinItalic.woff and /dev/null differ
diff --git a/app/assets/fonts/public-sans/PublicSans-ThinItalic.woff2 b/app/assets/fonts/public-sans/PublicSans-ThinItalic.woff2
index b8b1fbb51a9..cad2b41d0dc 100644
Binary files a/app/assets/fonts/public-sans/PublicSans-ThinItalic.woff2 and b/app/assets/fonts/public-sans/PublicSans-ThinItalic.woff2 differ
diff --git a/app/assets/stylesheets/_uswds-core.scss b/app/assets/stylesheets/_uswds-core.scss
index 3f9d36d90d1..726afafc28a 100644
--- a/app/assets/stylesheets/_uswds-core.scss
+++ b/app/assets/stylesheets/_uswds-core.scss
@@ -2,6 +2,7 @@
$theme-body-font-size: 'sm',
$theme-button-icon-gap: 0.5,
$theme-font-path: '',
+ $theme-font-weight-light: false,
$theme-image-path: '',
$theme-global-border-box-sizing: true,
$theme-global-link-styles: true,
diff --git a/app/assets/stylesheets/components/_banner.scss b/app/assets/stylesheets/components/_banner.scss
deleted file mode 100644
index 5fdca668e76..00000000000
--- a/app/assets/stylesheets/components/_banner.scss
+++ /dev/null
@@ -1,7 +0,0 @@
-@use 'uswds-core' as *;
-
-.usa-banner__inner {
- @include at-media('tablet') {
- justify-content: center;
- }
-}
diff --git a/app/assets/stylesheets/components/_index.scss b/app/assets/stylesheets/components/_index.scss
index 0647f995f31..4e1b4f67ab6 100644
--- a/app/assets/stylesheets/components/_index.scss
+++ b/app/assets/stylesheets/components/_index.scss
@@ -1,7 +1,6 @@
@forward 'account-header';
@forward 'alert-icon';
@forward 'alert';
-@forward 'banner';
@forward 'block-link';
@forward 'btn';
@forward 'card';
diff --git a/app/assets/stylesheets/components/_step-indicator.scss b/app/assets/stylesheets/components/_step-indicator.scss
index c9a4384a917..a9f4dc6c083 100644
--- a/app/assets/stylesheets/components/_step-indicator.scss
+++ b/app/assets/stylesheets/components/_step-indicator.scss
@@ -130,14 +130,3 @@ lg-step-indicator {
.step-indicator__step--current .step-indicator__step-title {
font-weight: bold;
}
-
-.step-indicator__step-subtitle {
- @include at-media-max('tablet') {
- @include sr-only;
- }
-
- @include at-media('tablet') {
- display: block;
- font-style: italic;
- }
-}
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 508f3c8f0f2..b83acd71750 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -111,6 +111,7 @@ def resolved_authn_context_result
@resolved_authn_context_result = Vot::Parser::Result.no_sp_result
else
@resolved_authn_context_result = AuthnContextResolver.new(
+ user: current_user,
service_provider: service_provider,
vtr: sp_session[:vtr],
acr_values: sp_session[:acr_values],
diff --git a/app/controllers/concerns/new_device_concern.rb b/app/controllers/concerns/new_device_concern.rb
new file mode 100644
index 00000000000..b96b1f64d05
--- /dev/null
+++ b/app/controllers/concerns/new_device_concern.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module NewDeviceConcern
+ def set_new_device_session
+ user_session[:new_device] = !current_user.authenticated_device?(cookie_uuid: cookies[:device])
+ end
+
+ def new_device?
+ user_session[:new_device] != false
+ end
+end
diff --git a/app/controllers/concerns/saml_idp_auth_concern.rb b/app/controllers/concerns/saml_idp_auth_concern.rb
index a40172b71ce..ed7b993576a 100644
--- a/app/controllers/concerns/saml_idp_auth_concern.rb
+++ b/app/controllers/concerns/saml_idp_auth_concern.rb
@@ -23,7 +23,7 @@ module SamlIdpAuthConcern
private
def block_biometric_requests_in_production
- if @saml_request_validator.parsed_vector_of_trust&.biometric_comparison? &&
+ if @saml_request_validator.biometric_comparison_requested? &&
!FeatureManagement.idv_allow_selfie_check?
render_not_acceptable
end
@@ -130,9 +130,12 @@ def default_ial_context
end
def response_authn_context
- saml_request.requested_vtr_authn_context ||
+ if saml_request.requested_vtr_authn_contexts.present?
+ resolved_authn_context_result.expanded_component_values
+ else
saml_request.requested_aal_authn_context ||
- default_aal_context
+ default_aal_context
+ end
end
def requested_ial_authn_context
diff --git a/app/controllers/concerns/two_factor_authenticatable_methods.rb b/app/controllers/concerns/two_factor_authenticatable_methods.rb
index e717304c48e..c4eea88da74 100644
--- a/app/controllers/concerns/two_factor_authenticatable_methods.rb
+++ b/app/controllers/concerns/two_factor_authenticatable_methods.rb
@@ -5,6 +5,7 @@ module TwoFactorAuthenticatableMethods
include RememberDeviceConcern
include SecureHeadersConcern
include MfaSetupConcern
+ include NewDeviceConcern
def auth_methods_session
@auth_methods_session ||= AuthMethodsSession.new(user_session:)
@@ -14,8 +15,7 @@ def handle_valid_verification_for_authentication_context(auth_method:)
mark_user_session_authenticated(auth_method:, authentication_type: :valid_2fa)
disavowal_event, disavowal_token = create_user_event_with_disavowal(:sign_in_after_2fa)
- if IdentityConfig.store.feature_new_device_alert_aggregation_enabled &&
- user_session[:new_device] != false
+ if IdentityConfig.store.feature_new_device_alert_aggregation_enabled && new_device?
if current_user.sign_in_new_device_at.blank?
current_user.update(sign_in_new_device_at: disavowal_event.created_at)
end
diff --git a/app/controllers/idv/agreement_controller.rb b/app/controllers/idv/agreement_controller.rb
index 7eb7df6926d..f18bd4492b9 100644
--- a/app/controllers/idv/agreement_controller.rb
+++ b/app/controllers/idv/agreement_controller.rb
@@ -26,7 +26,10 @@ def update
clear_future_steps!
skip_to_capture if params[:skip_hybrid_handoff]
- result = Idv::ConsentForm.new.submit(consent_form_params)
+ @consent_form = Idv::ConsentForm.new(
+ idv_consent_given: idv_session.idv_consent_given,
+ )
+ result = @consent_form.submit(consent_form_params)
analytics.idv_doc_auth_agreement_submitted(
**analytics_arguments.merge(result.to_h),
@@ -42,7 +45,7 @@ def update
redirect_to idv_hybrid_handoff_url
end
else
- redirect_to idv_agreement_url
+ render :show
end
end
diff --git a/app/controllers/idv/document_capture_controller.rb b/app/controllers/idv/document_capture_controller.rb
index 5325cb30c62..d7a98770153 100644
--- a/app/controllers/idv/document_capture_controller.rb
+++ b/app/controllers/idv/document_capture_controller.rb
@@ -53,7 +53,7 @@ def extra_view_variables
sp_name: decorated_sp_session.sp_name,
failure_to_proof_url: return_to_sp_failure_to_proof_url(step: 'document_capture'),
skip_doc_auth: idv_session.skip_doc_auth,
- skip_doc_auth_from_how_to_verify: false,
+ skip_doc_auth_from_how_to_verify: idv_session.skip_doc_auth_from_how_to_verify,
skip_doc_auth_from_handoff: idv_session.skip_doc_auth_from_handoff,
opted_in_to_in_person_proofing: idv_session.opted_in_to_in_person_proofing,
doc_auth_selfie_capture:,
@@ -73,6 +73,7 @@ def self.step_info
idv_session.skip_doc_auth_from_handoff ||
idv_session.skip_hybrid_handoff ||
idv_session.skip_doc_auth ||
+ idv_session.skip_doc_auth_from_how_to_verify ||
!idv_session.selfie_check_required || # desktop but selfie not required
idv_session.desktop_selfie_test_mode_enabled?
)
diff --git a/app/controllers/idv/how_to_verify_controller.rb b/app/controllers/idv/how_to_verify_controller.rb
index e9abd7d9f92..a41f98da563 100644
--- a/app/controllers/idv/how_to_verify_controller.rb
+++ b/app/controllers/idv/how_to_verify_controller.rb
@@ -39,11 +39,13 @@ def update
if how_to_verify_form_params['selection'] == Idv::HowToVerifyForm::REMOTE
idv_session.opted_in_to_in_person_proofing = false
idv_session.skip_doc_auth = false
+ idv_session.skip_doc_auth_from_how_to_verify = false
redirect_to idv_hybrid_handoff_url
else
idv_session.opted_in_to_in_person_proofing = true
idv_session.flow_path = 'standard'
idv_session.skip_doc_auth = true
+ idv_session.skip_doc_auth_from_how_to_verify = true
redirect_to idv_document_capture_url
end
@@ -70,6 +72,7 @@ def self.step_info
end,
undo_step: ->(idv_session:, user:) {
idv_session.skip_doc_auth = nil
+ idv_session.skip_doc_auth_from_how_to_verify = nil
idv_session.opted_in_to_in_person_proofing = nil
},
)
diff --git a/app/controllers/idv/hybrid_handoff_controller.rb b/app/controllers/idv/hybrid_handoff_controller.rb
index ba99e2d240c..3ccf028c36e 100644
--- a/app/controllers/idv/hybrid_handoff_controller.rb
+++ b/app/controllers/idv/hybrid_handoff_controller.rb
@@ -53,7 +53,8 @@ def self.selected_remote(idv_session:)
idv_session.service_provider&.in_person_proofing_enabled
idv_session.skip_doc_auth == false
else
- idv_session.skip_doc_auth.nil? || idv_session.skip_doc_auth == false
+ idv_session.skip_doc_auth.nil? ||
+ idv_session.skip_doc_auth == false
end
end
diff --git a/app/controllers/openid_connect/authorization_controller.rb b/app/controllers/openid_connect/authorization_controller.rb
index fa34a72a59d..85e80de2676 100644
--- a/app/controllers/openid_connect/authorization_controller.rb
+++ b/app/controllers/openid_connect/authorization_controller.rb
@@ -65,7 +65,7 @@ def block_biometric_requests_in_production
end
def biometric_comparison_requested?
- @authorize_form.parsed_vector_of_trust&.biometric_comparison?
+ @authorize_form.biometric_comparison_requested?
end
def check_sp_active
@@ -93,17 +93,31 @@ def set_devise_failure_redirect_for_concurrent_session_logout
end
def link_identity_to_service_provider
- @authorize_form.link_identity_to_service_provider(current_user, session.id)
+ @authorize_form.link_identity_to_service_provider(
+ current_user: current_user,
+ ial: resolved_authn_context_int_ial,
+ rails_session_id: session.id,
+ )
end
def ial_context
IalContext.new(
- ial: @authorize_form.ial,
+ ial: resolved_authn_context_int_ial,
service_provider: @authorize_form.service_provider,
user: current_user,
)
end
+ def resolved_authn_context_int_ial
+ if resolved_authn_context_result.ialmax?
+ 0
+ elsif resolved_authn_context_result.identity_proofing?
+ 2
+ else
+ 1
+ end
+ end
+
def handle_successful_handoff
track_events
SpHandoffBounce::AddHandoffTimeToSession.call(sp_session)
diff --git a/app/controllers/saml_idp_controller.rb b/app/controllers/saml_idp_controller.rb
index db8368526eb..9a9de7d9068 100644
--- a/app/controllers/saml_idp_controller.rb
+++ b/app/controllers/saml_idp_controller.rb
@@ -142,7 +142,7 @@ def log_external_saml_auth_request
requested_ial: requested_ial,
authn_context: saml_request&.requested_authn_contexts,
requested_aal_authn_context: saml_request&.requested_aal_authn_context,
- requested_vtr_authn_context: saml_request&.requested_vtr_authn_context,
+ requested_vtr_authn_contexts: saml_request&.requested_vtr_authn_contexts.presence,
force_authn: saml_request&.force_authn?,
final_auth_request: sp_session[:final_auth_request],
service_provider: saml_request&.issuer,
diff --git a/app/controllers/two_factor_authentication/backup_code_verification_controller.rb b/app/controllers/two_factor_authentication/backup_code_verification_controller.rb
index 4e8c05c55e3..10bcc18e140 100644
--- a/app/controllers/two_factor_authentication/backup_code_verification_controller.rb
+++ b/app/controllers/two_factor_authentication/backup_code_verification_controller.rb
@@ -3,6 +3,7 @@
module TwoFactorAuthentication
class BackupCodeVerificationController < ApplicationController
include TwoFactorAuthenticatable
+ include NewDeviceConcern
prepend_before_action :authenticate_user
before_action :check_sp_required_mfa
@@ -22,7 +23,7 @@ def create
@backup_code_form = BackupCodeVerificationForm.new(current_user)
result = @backup_code_form.submit(backup_code_params)
analytics.track_mfa_submit_event(
- result.to_h.merge(new_device: user_session[:new_device]),
+ result.to_h.merge(new_device: new_device?),
)
irs_attempts_api_tracker.mfa_login_backup_code(success: result.success?)
handle_result(result)
@@ -36,9 +37,7 @@ def all_codes_used?
def handle_last_code
generator = BackupCodeGenerator.new(current_user)
- generator.delete_existing_codes
- user_session[:backup_codes] = generator.generate
- generator.save(user_session[:backup_codes])
+ user_session[:backup_codes] = generator.delete_and_regenerate
flash[:info] = t('forms.backup_code.last_code')
redirect_to backup_code_refreshed_url
end
diff --git a/app/controllers/two_factor_authentication/otp_verification_controller.rb b/app/controllers/two_factor_authentication/otp_verification_controller.rb
index 31d836e8c88..3bf40093f41 100644
--- a/app/controllers/two_factor_authentication/otp_verification_controller.rb
+++ b/app/controllers/two_factor_authentication/otp_verification_controller.rb
@@ -4,6 +4,7 @@ module TwoFactorAuthentication
class OtpVerificationController < ApplicationController
include TwoFactorAuthenticatable
include MfaSetupConcern
+ include NewDeviceConcern
before_action :check_sp_required_mfa
before_action :confirm_multiple_factors_enabled
@@ -132,7 +133,7 @@ def form_params
end
def post_analytics(result)
- properties = result.to_h.merge(analytics_properties, new_device: user_session[:new_device])
+ properties = result.to_h.merge(analytics_properties, new_device: new_device?)
analytics.multi_factor_auth_setup(**properties) if context == 'confirmation'
analytics.track_mfa_submit_event(properties)
diff --git a/app/controllers/two_factor_authentication/personal_key_verification_controller.rb b/app/controllers/two_factor_authentication/personal_key_verification_controller.rb
index 64b0a8c85c8..85302e11991 100644
--- a/app/controllers/two_factor_authentication/personal_key_verification_controller.rb
+++ b/app/controllers/two_factor_authentication/personal_key_verification_controller.rb
@@ -3,6 +3,7 @@
module TwoFactorAuthentication
class PersonalKeyVerificationController < ApplicationController
include TwoFactorAuthenticatable
+ include NewDeviceConcern
prepend_before_action :authenticate_user
before_action :check_personal_key_enabled
@@ -28,7 +29,7 @@ def track_analytics(result)
analytics_hash = result.to_h.merge(
multi_factor_auth_method: 'personal-key',
multi_factor_auth_method_created_at: mfa_created_at&.strftime('%s%L'),
- new_device: user_session[:new_device],
+ new_device: new_device?,
)
analytics.track_mfa_submit_event(analytics_hash)
diff --git a/app/controllers/two_factor_authentication/piv_cac_verification_controller.rb b/app/controllers/two_factor_authentication/piv_cac_verification_controller.rb
index 39b89f881fa..56151472bfa 100644
--- a/app/controllers/two_factor_authentication/piv_cac_verification_controller.rb
+++ b/app/controllers/two_factor_authentication/piv_cac_verification_controller.rb
@@ -4,6 +4,7 @@ module TwoFactorAuthentication
class PivCacVerificationController < ApplicationController
include TwoFactorAuthenticatable
include PivCacConcern
+ include NewDeviceConcern
before_action :confirm_piv_cac_enabled, only: :show
before_action :reset_attempt_count_if_user_no_longer_locked_out, only: :show
@@ -105,7 +106,7 @@ def analytics_properties
context: context,
multi_factor_auth_method: 'piv_cac',
piv_cac_configuration_id: piv_cac_verification_form&.piv_cac_configuration&.id,
- new_device: user_session[:new_device],
+ new_device: new_device?,
}
end
end
diff --git a/app/controllers/two_factor_authentication/totp_verification_controller.rb b/app/controllers/two_factor_authentication/totp_verification_controller.rb
index eaed664380a..111c8a52c1b 100644
--- a/app/controllers/two_factor_authentication/totp_verification_controller.rb
+++ b/app/controllers/two_factor_authentication/totp_verification_controller.rb
@@ -3,6 +3,7 @@
module TwoFactorAuthentication
class TotpVerificationController < ApplicationController
include TwoFactorAuthenticatable
+ include NewDeviceConcern
before_action :check_sp_required_mfa
before_action :confirm_totp_enabled
@@ -20,7 +21,7 @@ def show
def create
result = TotpVerificationForm.new(current_user, params.require(:code).strip).submit
- analytics.track_mfa_submit_event(result.to_h.merge(new_device: user_session[:new_device]))
+ analytics.track_mfa_submit_event(result.to_h.merge(new_device: new_device?))
irs_attempts_api_tracker.mfa_login_totp(success: result.success?)
if result.success?
diff --git a/app/controllers/two_factor_authentication/webauthn_verification_controller.rb b/app/controllers/two_factor_authentication/webauthn_verification_controller.rb
index 57072bccfc6..458ebf650a8 100644
--- a/app/controllers/two_factor_authentication/webauthn_verification_controller.rb
+++ b/app/controllers/two_factor_authentication/webauthn_verification_controller.rb
@@ -4,6 +4,7 @@ module TwoFactorAuthentication
# The WebauthnVerificationController class is responsible webauthn verification at sign in
class WebauthnVerificationController < ApplicationController
include TwoFactorAuthenticatable
+ include NewDeviceConcern
before_action :check_sp_required_mfa
before_action :check_if_device_supports_platform_auth, only: :show
@@ -22,7 +23,7 @@ def confirm
**analytics_properties,
multi_factor_auth_method_created_at:
webauthn_configuration_or_latest.created_at.strftime('%s%L'),
- new_device: user_session[:new_device],
+ new_device: new_device?,
)
if analytics_properties[:multi_factor_auth_method] == 'webauthn_platform'
diff --git a/app/controllers/users/backup_code_setup_controller.rb b/app/controllers/users/backup_code_setup_controller.rb
index b01007d7f99..03580ac54cc 100644
--- a/app/controllers/users/backup_code_setup_controller.rb
+++ b/app/controllers/users/backup_code_setup_controller.rb
@@ -14,18 +14,30 @@ class BackupCodeSetupController < ApplicationController
before_action :apply_secure_headers_override
before_action :authorize_backup_code_disable, only: [:delete]
before_action :confirm_recently_authenticated_2fa, except: [:reminder, :continue]
- before_action :validate_internal_referrer?, only: [:index]
+ before_action :validate_multi_mfa_selection, only: [:index]
helper_method :in_multi_mfa_selection_flow?
def index
+ result = BackupCodeSetupForm.new(current_user).submit
+ visit_result = result.to_h.merge(analytics_properties_for_visit)
+ analytics.backup_code_setup_visit(**visit_result)
+ irs_attempts_api_tracker.mfa_enroll_backup_code(success: result.success?)
+
generate_codes
+ track_backup_codes_created
+ render :create
+ end
+
+ def new; end
+
+ def create
result = BackupCodeSetupForm.new(current_user).submit
visit_result = result.to_h.merge(analytics_properties_for_visit)
analytics.backup_code_setup_visit(**visit_result)
irs_attempts_api_tracker.mfa_enroll_backup_code(success: result.success?)
- save_backup_codes
+ generate_codes
track_backup_codes_created
end
@@ -43,7 +55,7 @@ def confirm_delete; end
def refreshed
@codes = user_session[:backup_codes]
- render 'index'
+ render :create
end
def delete
@@ -67,8 +79,12 @@ def confirm_backup_codes; end
private
- def validate_internal_referrer?
- redirect_to root_url unless internal_referrer?
+ def validate_multi_mfa_selection
+ if IdentityConfig.store.backup_code_confirm_setup_screen_enabled
+ redirect_to backup_code_confirm_setup_url unless in_multi_mfa_selection_flow?
+ else
+ redirect_to root_url unless internal_referrer?
+ end
end
def internal_referrer?
@@ -81,6 +97,13 @@ def analytics_properties_for_visit
end
def track_backup_codes_created
+ handle_valid_verification_for_confirmation_context(
+ auth_method: TwoFactorAuthenticatable::AuthMethod::BACKUP_CODE,
+ )
+ event = PushNotification::RecoveryInformationChangedEvent.new(user: current_user)
+ PushNotification::HttpPush.deliver(event)
+ create_user_event(:backup_codes_added)
+
analytics.backup_code_created(
enabled_mfa_methods_count: mfa_user.enabled_mfa_methods_count,
in_account_creation_flow: in_account_creation_flow?,
@@ -98,7 +121,7 @@ def ensure_backup_codes_in_session
def generate_codes
revoke_remember_device(current_user) if current_user.backup_code_configurations.any?
- @codes = generator.generate
+ @codes = generator.delete_and_regenerate
user_session[:backup_codes] = @codes
end
@@ -111,16 +134,6 @@ def set_backup_code_setup_presenter
)
end
- def save_backup_codes
- handle_valid_verification_for_confirmation_context(
- auth_method: TwoFactorAuthenticatable::AuthMethod::BACKUP_CODE,
- )
- generator.save(user_session[:backup_codes])
- event = PushNotification::RecoveryInformationChangedEvent.new(user: current_user)
- PushNotification::HttpPush.deliver(event)
- create_user_event(:backup_codes_added)
- end
-
def generator
@generator ||= BackupCodeGenerator.new(current_user)
end
diff --git a/app/controllers/users/piv_cac_login_controller.rb b/app/controllers/users/piv_cac_login_controller.rb
index 1bcb2b34b47..19a2181ef2a 100644
--- a/app/controllers/users/piv_cac_login_controller.rb
+++ b/app/controllers/users/piv_cac_login_controller.rb
@@ -5,6 +5,7 @@ class PivCacLoginController < ApplicationController
include PivCacConcern
include VerifySpAttributesConcern
include TwoFactorAuthenticatableMethods
+ include NewDeviceConcern
def new
if params.key?(:token)
@@ -74,7 +75,7 @@ def process_valid_submission
presented: true,
)
- user_session[:new_device] = current_user.new_device?(cookie_uuid: cookies[:device])
+ set_new_device_session
handle_valid_verification_for_authentication_context(
auth_method: TwoFactorAuthenticatable::AuthMethod::PIV_CAC,
)
diff --git a/app/controllers/users/sessions_controller.rb b/app/controllers/users/sessions_controller.rb
index 88dde2be88e..b6015b46228 100644
--- a/app/controllers/users/sessions_controller.rb
+++ b/app/controllers/users/sessions_controller.rb
@@ -8,6 +8,7 @@ class SessionsController < Devise::SessionsController
include Ial2ProfileConcern
include Api::CsrfTokenConcern
include ForcedReauthenticationConcern
+ include NewDeviceConcern
rescue_from ActionController::InvalidAuthenticityToken, with: :redirect_to_signin
@@ -112,8 +113,9 @@ def process_locked_out_user
def handle_valid_authentication
sign_in(resource_name, resource)
cache_profiles(auth_params[:password])
- user_session[:new_device] = current_user.new_device?(cookie_uuid: cookies[:device])
- create_user_event(:sign_in_before_2fa)
+ set_new_device_session
+ event, = create_user_event(:sign_in_before_2fa)
+ UserAlerts::AlertUserAboutNewDevice.schedule_alert(event:) if new_device?
EmailAddress.update_last_sign_in_at_on_user_id_and_email(
user_id: current_user.id,
email: auth_params[:email],
diff --git a/app/forms/backup_code_verification_form.rb b/app/forms/backup_code_verification_form.rb
index 3ca8e9b6cc2..2254e3db070 100644
--- a/app/forms/backup_code_verification_form.rb
+++ b/app/forms/backup_code_verification_form.rb
@@ -19,18 +19,19 @@ def submit(params)
attr_reader :user, :backup_code
def valid_backup_code?
- backup_code_config.present?
+ valid_backup_code_config_created_at.present?
end
- def backup_code_config
- @backup_code_config ||= BackupCodeGenerator.new(@user).
- if_valid_consume_code_return_config(backup_code)
+ def valid_backup_code_config_created_at
+ return @valid_backup_code_config_created_at if defined?(@valid_backup_code_config_created_at)
+ @valid_backup_code_config_created_at = BackupCodeGenerator.new(@user).
+ if_valid_consume_code_return_config_created_at(backup_code)
end
def extra_analytics_attributes
{
multi_factor_auth_method: 'backup_code',
- multi_factor_auth_method_created_at: backup_code_config&.created_at&.strftime('%s%L'),
+ multi_factor_auth_method_created_at: valid_backup_code_config_created_at&.strftime('%s%L'),
}
end
end
diff --git a/app/forms/idv/doc_pii_form.rb b/app/forms/idv/doc_pii_form.rb
index 6b62481c092..f29c13094c6 100644
--- a/app/forms/idv/doc_pii_form.rb
+++ b/app/forms/idv/doc_pii_form.rb
@@ -43,6 +43,8 @@ def submit
extra: {
pii_like_keypaths: self.class.pii_like_keypaths,
attention_with_barcode: attention_with_barcode?,
+ id_issued_status: pii_from_doc[:state_id_issued].present? ? 'present' : 'missing',
+ id_expiration_status: pii_from_doc[:state_id_expiration].present? ? 'present' : 'missing',
},
)
response.pii_from_doc = pii_from_doc
diff --git a/app/forms/openid_connect_authorize_form.rb b/app/forms/openid_connect_authorize_form.rb
index bd3970803cd..23c4f404af0 100644
--- a/app/forms/openid_connect_authorize_form.rb
+++ b/app/forms/openid_connect_authorize_form.rb
@@ -91,13 +91,16 @@ def service_provider
@service_provider = ServiceProvider.find_by(issuer: client_id)
end
- def link_identity_to_service_provider(current_user, rails_session_id)
+ def link_identity_to_service_provider(
+ current_user:,
+ ial:,
+ rails_session_id:
+ )
identity_linker = IdentityLinker.new(current_user, service_provider)
@identity = identity_linker.link_identity(
nonce: nonce,
rails_session_id: rails_session_id,
ial: ial,
- aal: aal,
acr_values: acr_values&.join(' '),
vtr: vtr,
requested_aal_value: requested_aal_value,
@@ -117,45 +120,25 @@ def ial_values
acr_values.filter { |acr| acr.include?('ial') || acr.include?('loa') }
end
- def ial
- if parsed_vector_of_trust&.identity_proofing?
- 2
- elsif parsed_vector_of_trust.present?
- 1
- else
- Saml::Idp::Constants::AUTHN_CONTEXT_CLASSREF_TO_IAL[ial_values.sort.max]
- end
- end
-
def aal_values
acr_values.filter { |acr| acr.include?('aal') }
end
- def aal
- if parsed_vector_of_trust&.aal2?
- 2
- elsif parsed_vector_of_trust.present?
- 1
- else
- Saml::Idp::Constants::AUTHN_CONTEXT_CLASSREF_TO_AAL[requested_aal_value]
- end
- end
-
def requested_aal_value
highest_level_aal(aal_values) ||
Saml::Idp::Constants::DEFAULT_AAL_AUTHN_CONTEXT_CLASSREF
end
- def biometric_comparison_required?
- parsed_vector_of_trust&.biometric_comparison?
+ def biometric_comparison_requested?
+ !!parsed_vectors_of_trust&.any?(&:biometric_comparison?)
end
- def parsed_vector_of_trust
- return @parsed_vector_of_trust if defined?(@parsed_vector_of_trust)
+ def parsed_vectors_of_trust
+ return @parsed_vectors_of_trust if defined?(@parsed_vectors_of_trust)
- @parsed_vector_of_trust = begin
+ @parsed_vectors_of_trust = begin
if vtr.is_a?(Array) && !vtr.empty?
- Vot::Parser.new(vector_of_trust: vtr.first).parse
+ vtr.map { |vot| Vot::Parser.new(vector_of_trust: vot).parse }
end
rescue Vot::Parser::ParseException
nil
@@ -209,7 +192,7 @@ def validate_acr_values
def validate_vtr
return if vtr.blank?
- return if parsed_vector_of_trust.present?
+ return if parsed_vectors_of_trust.present?
errors.add(
:vtr, t('openid_connect.authorization.errors.no_valid_vtr'),
type: :no_valid_vtr
@@ -336,7 +319,11 @@ def sp_defaults_to_identity_proofing?
end
def identity_proofing_requested?
- ial == 2
+ if parsed_vectors_of_trust.present?
+ parsed_vectors_of_trust.any?(&:identity_proofing?)
+ else
+ Saml::Idp::Constants::AUTHN_CONTEXT_CLASSREF_TO_IAL[ial_values.sort.max] == 2
+ end
end
def identity_proofing_service_provider?
@@ -348,7 +335,7 @@ def ialmax_allowed_for_sp?
end
def ialmax_requested?
- ial == 0
+ Saml::Idp::Constants::AUTHN_CONTEXT_CLASSREF_TO_IAL[ial_values.sort.max] == 0
end
def highest_level_aal(aal_values)
diff --git a/app/javascript/packages/document-capture/components/acuant-capture.tsx b/app/javascript/packages/document-capture/components/acuant-capture.tsx
index 6bc85b80884..6a7bf111812 100644
--- a/app/javascript/packages/document-capture/components/acuant-capture.tsx
+++ b/app/javascript/packages/document-capture/components/acuant-capture.tsx
@@ -529,7 +529,6 @@ function AcuantCapture(
});
setImageCaptureText('');
- setIsCapturingEnvironment(true);
}
function onSelfieCaptureClosed() {
diff --git a/app/javascript/packages/document-capture/components/acuant-selfie-capture-canvas.jsx b/app/javascript/packages/document-capture/components/acuant-selfie-capture-canvas.jsx
index 86dab1889a2..916f75a9ffd 100644
--- a/app/javascript/packages/document-capture/components/acuant-selfie-capture-canvas.jsx
+++ b/app/javascript/packages/document-capture/components/acuant-selfie-capture-canvas.jsx
@@ -21,6 +21,16 @@ function AcuantSelfieCaptureCanvas({ imageCaptureText, onSelfieCaptureClosed })
// The Acuant SDK script AcuantPassiveLiveness attaches to whatever element has
// this id. It then uses that element as the root for the full screen selfie capture
const acuantCaptureContainerId = 'acuant-face-capture-container';
+
+ // This solves a fairly nasty bug for screenreader users where the screenreader focus would jump away
+ // from the capture button (added by Acuant SDK) to the button in this component. Specifically we
+ // need to detect when Acuant actually hydrates in their capture screen and hide the button.
+ // See PR 10668 for more information.
+ const elementInShadow = document
+ ?.getElementById('acuant-face-capture-camera')
+ ?.shadowRoot?.getElementById('cameraContainer');
+ const loadedAcuantCamera = !!elementInShadow;
+
return (
<>
{!isReady &&
- <%= t('doc_auth.info.hybrid_handoff_ipp_html') %> -
-- <%= link_to t('in_person_proofing.headings.prepare'), idv_document_capture_path(step: :hybrid_handoff) %> -
+ <% if @direct_ipp_with_selfie_enabled %> ++ <%= t('doc_auth.info.hybrid_handoff_ipp_html') %> +
++ <%= link_to t('in_person_proofing.headings.prepare'), idv_document_capture_path(step: :hybrid_handoff) %> +
+