diff --git a/.erb-lint.yml b/.erb_lint.yml similarity index 100% rename from .erb-lint.yml rename to .erb_lint.yml diff --git a/Gemfile b/Gemfile index 1030f0c677c..ee19f1969e6 100644 --- a/Gemfile +++ b/Gemfile @@ -105,7 +105,7 @@ group :development, :test do gem 'brakeman', require: false gem 'bullet', '~> 7.0' gem 'capybara-webmock', git: 'https://github.com/hashrocket/capybara-webmock.git', ref: 'd3f3b7c' - gem 'erb_lint', '~> 0.5.0', require: false + gem 'erb_lint', '~> 0.7.0', require: false gem 'i18n-tasks', '~> 1.0' gem 'knapsack' gem 'listen' diff --git a/Gemfile.lock b/Gemfile.lock index dda8909ff93..037d8d04e17 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -305,12 +305,12 @@ GEM htmlentities (~> 4.3.3) launchy (~> 2.1) mail (~> 2.7) - erb_lint (0.5.0) + erb_lint (0.7.0) activesupport better_html (>= 2.0.1) parser (>= 2.7.1.4) rainbow - rubocop + rubocop (>= 1) smart_properties errbase (0.2.1) erubi (1.13.0) @@ -779,7 +779,7 @@ DEPENDENCIES devise (~> 4.8) dotiw (>= 4.0.1) email_spec - erb_lint (~> 0.5.0) + erb_lint (~> 0.7.0) factory_bot_rails (>= 6.2.0) faker faraday (~> 2) diff --git a/Makefile b/Makefile index f10d272378a..482082e652d 100644 --- a/Makefile +++ b/Makefile @@ -63,7 +63,7 @@ check: lint test ## Runs lint tests and spec tests lint: ## Runs all lint tests # Ruby - @echo "--- erb-lint ---" + @echo "--- erb_lint ---" make lint_erb @echo "--- rubocop ---" mkdir -p tmp @@ -112,7 +112,7 @@ audit: ## Checks packages for vulnerabilities yarn audit --groups dependencies; test $$? -le 7 lint_erb: ## Lints ERB files - bundle exec erblint app/views app/components + bundle exec erb_lint app/views app/components 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) @@ -181,8 +181,8 @@ lint_spec_file_name: lintfix: ## Try to automatically fix any Ruby, ERB, JavaScript, YAML, or CSS lint errors @echo "--- rubocop fix ---" bundle exec rubocop -a - @echo "--- erblint fix ---" - bundle exec erblint app/views app/components -a + @echo "--- erb_lint fix ---" + bundle exec erb_lint app/views app/components -a @echo "--- eslint fix ---" yarn lint --fix @echo "--- stylelint fix ---" diff --git a/app/controllers/concerns/ial2_profile_concern.rb b/app/controllers/concerns/ial2_profile_concern.rb index 44951aefbe0..679660a8d59 100644 --- a/app/controllers/concerns/ial2_profile_concern.rb +++ b/app/controllers/concerns/ial2_profile_concern.rb @@ -23,7 +23,7 @@ def cache_profile_and_handle_errors(raw_password, profile) cacher.save(raw_password, profile) rescue Encryption::EncryptionError => err if profile - profile.deactivate(:encryption_error) + profile.deactivate_due_to_encryption_error analytics.profile_encryption_invalid(error: err.message) end end diff --git a/app/controllers/concerns/idv/document_capture_concern.rb b/app/controllers/concerns/idv/document_capture_concern.rb index 790f0c64907..746657959a4 100644 --- a/app/controllers/concerns/idv/document_capture_concern.rb +++ b/app/controllers/concerns/idv/document_capture_concern.rb @@ -81,6 +81,38 @@ def redirect_to_correct_vendor(vendor, in_hybrid_mobile) redirect_to correct_path end + def fetch_test_verification_data + return unless IdentityConfig.store.socure_docv_verification_data_test_mode + + docv_transaction_token_override = params.permit(:docv_token)[:docv_token] + return unless IdentityConfig.store.socure_docv_verification_data_test_mode_tokens. + include?(docv_transaction_token_override) + + SocureDocvResultsJob.perform_now( + document_capture_session_uuid:, + docv_transaction_token_override:, + async: true, + ) + end + + def track_document_request_event(document_request:, document_response:, timer:) + document_request_body = JSON.parse(document_request.body, symbolize_names: true)[:config] + response_hash = document_response.to_h + log_extras = { + reference_id: response_hash[:referenceId], + vendor: 'Socure', + vendor_request_time_in_ms: timer.results['vendor_request'], + success: @url.present?, + document_type: document_request_body[:documentType], + docv_transaction_token: response_hash.dig(:data, :docvTransactionToken), + } + analytics_hash = log_extras.merge(analytics_arguments). + merge(document_request_body).except( + :documentType, # requested document type + ).merge(response_body: document_response.to_h) + analytics.idv_socure_document_request_submitted(**analytics_hash) + end + private def track_document_issuing_state(user, state) diff --git a/app/controllers/idv/account_verified_cta_visited_controller.rb b/app/controllers/idv/account_verified_cta_visited_controller.rb index 550e65ea2c1..b058db1b588 100644 --- a/app/controllers/idv/account_verified_cta_visited_controller.rb +++ b/app/controllers/idv/account_verified_cta_visited_controller.rb @@ -22,7 +22,8 @@ def redirect_url if issuer.blank? root_url else - sp_return_url_resolver&.return_to_sp_url + sp_return_url_resolver&.post_idv_follow_up_url || + sp_return_url_resolver&.return_to_sp_url end end diff --git a/app/controllers/idv/by_mail/sp_follow_up_controller.rb b/app/controllers/idv/by_mail/sp_follow_up_controller.rb new file mode 100644 index 00000000000..86381f6e2da --- /dev/null +++ b/app/controllers/idv/by_mail/sp_follow_up_controller.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +module Idv + module ByMail + class SpFollowUpController < ApplicationController + include Idv::AvailabilityConcern + + before_action :confirm_two_factor_authenticated + before_action :confirm_needs_sp_follow_up + + def new + analytics.track_event(:idv_by_mail_sp_follow_up_visited, **analytics_params) + @presenter = Idv::ByMail::SpFollowUpPresenter.new(current_user:) + end + + def show + analytics.track_event(:idv_by_mail_sp_follow_up_submitted, **analytics_params) + + sp_return_url_resolver = SpReturnUrlResolver.new( + service_provider: current_user.active_profile.initiating_service_provider, + ) + redirect_url = sp_return_url_resolver.post_idv_follow_up_url || + sp_return_url_resolver.return_to_sp_url + redirect_to(redirect_url, allow_other_host: true) + end + + def cancel + analytics.track_event(:idv_by_mail_sp_follow_up_cancelled, **analytics_params) + redirect_to account_url + end + + private + + def analytics_params + initiating_service_provider = current_user.active_profile.initiating_service_provider + { + initiating_service_provider: initiating_service_provider.issuer, + } + end + + def confirm_needs_sp_follow_up + return if current_user.identity_verified? && + current_user.active_profile.initiating_service_provider.present? && + !current_sp.present? + redirect_to account_url + end + end + end +end diff --git a/app/controllers/idv/enter_password_controller.rb b/app/controllers/idv/enter_password_controller.rb index 64768ea7ec8..c91ab6044a3 100644 --- a/app/controllers/idv/enter_password_controller.rb +++ b/app/controllers/idv/enter_password_controller.rb @@ -127,7 +127,7 @@ def confirm_current_password end def init_profile - idv_session.create_profile_from_applicant_with_password( + profile = idv_session.create_profile_from_applicant_with_password( password, is_enhanced_ipp: resolved_authn_context_result.enhanced_ipp?, proofing_components: ProofingComponents.new( @@ -137,12 +137,13 @@ def init_profile user_session:, ).to_h, ) - if idv_session.verify_by_mail? + + if profile.gpo_verification_pending? current_user.send_email_to_all_addresses(:verify_by_mail_letter_requested) log_letter_enqueued_analytics(resend: false) end - if idv_session.profile.active? + if profile.active? create_user_event(:account_verified) UserAlerts::AlertUserAboutAccountVerified.call( profile: idv_session.profile, diff --git a/app/controllers/idv/how_to_verify_controller.rb b/app/controllers/idv/how_to_verify_controller.rb index 233d6165d6d..5b65ae67cfb 100644 --- a/app/controllers/idv/how_to_verify_controller.rb +++ b/app/controllers/idv/how_to_verify_controller.rb @@ -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 @@ -86,8 +87,16 @@ def how_to_verify_form_params end def set_how_to_verify_presenter + @mobile_required = mobile_required? @selfie_required = idv_session.selfie_check_required - @presenter = Idv::HowToVerifyPresenter.new(selfie_check_required: @selfie_required) + @presenter = Idv::HowToVerifyPresenter.new( + mobile_required: @mobile_required, + selfie_check_required: @selfie_required, + ) + end + + def mobile_required? + idv_session.selfie_check_required || doc_auth_vendor == Idp::Constants::Vendors::SOCURE end end end diff --git a/app/controllers/idv/hybrid_mobile/socure/document_capture_controller.rb b/app/controllers/idv/hybrid_mobile/socure/document_capture_controller.rb index 44fccfa0182..5fa8e17c763 100644 --- a/app/controllers/idv/hybrid_mobile/socure/document_capture_controller.rb +++ b/app/controllers/idv/hybrid_mobile/socure/document_capture_controller.rb @@ -14,6 +14,7 @@ class DocumentCaptureController < ApplicationController before_action :check_valid_document_capture_session, except: [:update] before_action -> { redirect_to_correct_vendor(Idp::Constants::Vendors::SOCURE, true) }, only: :show + before_action :fetch_test_verification_data, only: [:update] def show Funnel::DocAuth::RegisterStep.new(document_capture_user.id, sp_session[:issuer]). @@ -24,12 +25,16 @@ def show redirect_url: idv_hybrid_mobile_socure_document_capture_update_url, language: I18n.locale, ) - document_response = document_request.fetch + timer = JobHelpers::Timer.new + document_response = timer.time('vendor_request') do + document_request.fetch + end - @document_request = document_request - @document_response = document_response @url = document_response.dig(:data, :url) + track_document_request_event(document_request:, document_response:, timer:) + + # placeholder until we get an error page for url not being present if @url.nil? redirect_to idv_hybrid_mobile_socure_document_capture_errors_url return @@ -47,9 +52,6 @@ def show :url, ) document_capture_session.save - # useful for analytics - @msg = document_response[:msg] - @reference_id = document_response[:referenceId] end def update diff --git a/app/controllers/idv/personal_key_controller.rb b/app/controllers/idv/personal_key_controller.rb index 358b1f97fd0..8599d8291b8 100644 --- a/app/controllers/idv/personal_key_controller.rb +++ b/app/controllers/idv/personal_key_controller.rb @@ -72,6 +72,8 @@ def next_step idv_please_call_url elsif session[:sp] sign_up_completed_url + elsif idv_session.address_verification_mechanism == 'gpo' + idv_sp_follow_up_path else after_sign_in_path_for(current_user) end diff --git a/app/controllers/idv/socure/document_capture_controller.rb b/app/controllers/idv/socure/document_capture_controller.rb index 3f29ad659e1..8beee4f8a92 100644 --- a/app/controllers/idv/socure/document_capture_controller.rb +++ b/app/controllers/idv/socure/document_capture_controller.rb @@ -14,6 +14,7 @@ class DocumentCaptureController < ApplicationController before_action :confirm_step_allowed before_action -> { redirect_to_correct_vendor(Idp::Constants::Vendors::SOCURE, false) }, only: :show + before_action :fetch_test_verification_data, only: [:update] # reconsider and maybe remove these when implementing the real # update handler @@ -34,13 +35,15 @@ def show redirect_url: idv_socure_document_capture_update_url, language: I18n.locale, ) + timer = JobHelpers::Timer.new + document_response = timer.time('vendor_request') do + document_request.fetch + end - document_response = document_request.fetch - - @document_request = document_request - @document_response = document_response @url = document_response.dig(:data, :url) + track_document_request_event(document_request:, document_response:, timer:) + # placeholder until we get an error page for url not being present if @url.nil? redirect_to idv_socure_document_capture_errors_url @@ -60,10 +63,6 @@ def show :url, ) document_capture_session.save - - # useful for analytics - @msg = document_response[:msg] - @reference_id = document_response[:referenceId] end def update diff --git a/app/controllers/users/webauthn_platform_recommended_controller.rb b/app/controllers/users/webauthn_platform_recommended_controller.rb index 7c8395dfdcc..aa18b9b6eeb 100644 --- a/app/controllers/users/webauthn_platform_recommended_controller.rb +++ b/app/controllers/users/webauthn_platform_recommended_controller.rb @@ -39,7 +39,7 @@ def dismiss_redirect_path if opted_to_add? webauthn_setup_path(platform: true) elsif in_account_creation_flow? - next_setup_path + next_setup_path || after_mfa_setup_path else after_sign_in_path_for(current_user) end diff --git a/app/jobs/socure_docv_results_job.rb b/app/jobs/socure_docv_results_job.rb index 25729078575..b4142a3b2b8 100644 --- a/app/jobs/socure_docv_results_job.rb +++ b/app/jobs/socure_docv_results_job.rb @@ -3,12 +3,13 @@ class SocureDocvResultsJob < ApplicationJob queue_as :high_socure_docv - attr_reader :document_capture_session_uuid, :async + attr_reader :document_capture_session_uuid, :async, :docv_transaction_token_override # @param [String] document_capture_session_uuid - def perform(document_capture_session_uuid:, async: true) + def perform(document_capture_session_uuid:, async: true, docv_transaction_token_override: nil) @document_capture_session_uuid = document_capture_session_uuid @async = async + @docv_transaction_token_override = docv_transaction_token_override raise "DocumentCaptureSession not found: #{document_capture_session_uuid}" unless document_capture_session @@ -51,6 +52,7 @@ def log_verification_request(docv_result_response:, vendor_request_time_in_ms:) def socure_document_verification_result DocAuth::Socure::Requests::DocvResultRequest.new( document_capture_session_uuid:, + docv_transaction_token_override:, ).fetch end diff --git a/app/models/profile.rb b/app/models/profile.rb index 2052eb33eaf..e05d3c0a33f 100644 --- a/app/models/profile.rb +++ b/app/models/profile.rb @@ -191,6 +191,20 @@ def deactivate(reason) update!(active: false, deactivation_reason: reason) end + # Update the profile's deactivation reason to "encryption_error". As a + # side-effect, when the profile has an associated pending in-person + # enrollment it will be updated to have a status of "cancelled". + def deactivate_due_to_encryption_error + update!( + active: false, + deactivation_reason: :encryption_error, + ) + + if in_person_enrollment&.pending? + in_person_enrollment.cancelled! + end + end + def fraud_deactivation_reason? fraud_review_pending? || fraud_rejection? end diff --git a/app/presenters/idv/account_verified_email_presenter.rb b/app/presenters/idv/account_verified_email_presenter.rb index 46477f0f201..a7a5748ce40 100644 --- a/app/presenters/idv/account_verified_email_presenter.rb +++ b/app/presenters/idv/account_verified_email_presenter.rb @@ -16,7 +16,7 @@ def service_provider end def show_cta? - !service_provider || service_provider_homepage_url.present? + !service_provider || service_provider_post_idv_follow_up_url.present? end def sign_in_url @@ -32,11 +32,11 @@ def sign_in_url end def displayed_sign_in_url - service_provider_homepage_url || root_url + service_provider_post_idv_follow_up_url || root_url end - def service_provider_homepage_url - sp_return_url_resolver.homepage_url if service_provider + def service_provider_post_idv_follow_up_url + sp_return_url_resolver.post_idv_follow_up_url if service_provider end def sp_name diff --git a/app/presenters/idv/by_mail/sp_follow_up_presenter.rb b/app/presenters/idv/by_mail/sp_follow_up_presenter.rb new file mode 100644 index 00000000000..b63cc7b2a78 --- /dev/null +++ b/app/presenters/idv/by_mail/sp_follow_up_presenter.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +module Idv + module ByMail + class SpFollowUpPresenter + include ActionView::Helpers::TranslationHelper + + attr_reader :current_user + + def initialize(current_user:) + @current_user = current_user + end + + def heading + t( + 'idv.by_mail.sp_follow_up.heading', + service_provider: initiating_service_provider_name, + ) + end + + def body + t( + 'idv.by_mail.sp_follow_up.body', + service_provider: initiating_service_provider_name, + app_name: APP_NAME, + ) + end + + private + + def initiating_service_provider_name + initiating_service_provider.friendly_name + end + + def initiating_service_provider + @initiating_service_provider ||= current_user.active_profile.initiating_service_provider + end + end + end +end diff --git a/app/presenters/idv/how_to_verify_presenter.rb b/app/presenters/idv/how_to_verify_presenter.rb index ed3ba1574cd..ee161ca8284 100644 --- a/app/presenters/idv/how_to_verify_presenter.rb +++ b/app/presenters/idv/how_to_verify_presenter.rb @@ -4,22 +4,23 @@ class Idv::HowToVerifyPresenter include ActionView::Helpers::TagHelper include ActionView::Helpers::TranslationHelper - attr_reader :selfie_required + attr_reader :mobile_required, :selfie_required - def initialize(selfie_check_required:) + def initialize(mobile_required:, selfie_check_required:) + @mobile_required = mobile_required @selfie_required = selfie_check_required end def how_to_verify_info - if selfie_required - t('doc_auth.info.how_to_verify_selfie') + if mobile_required + t('doc_auth.info.how_to_verify_mobile') else t('doc_auth.info.how_to_verify') end end def asset_url - if selfie_required + if mobile_required 'idv/mobile-phone-icon.svg' else 'idv/remote.svg' @@ -27,7 +28,7 @@ def asset_url end def alt_text - if selfie_required + if mobile_required t('image_description.phone_icon') else t('image_description.laptop_and_phone') @@ -35,32 +36,31 @@ def alt_text end def verify_online_text - if selfie_required - t('doc_auth.headings.verify_online_selfie') + if mobile_required + t('doc_auth.headings.verify_online_mobile') else t('doc_auth.headings.verify_online') end end def verify_online_instruction - if selfie_required - t('doc_auth.info.verify_online_instruction_selfie') - else - t('doc_auth.info.verify_online_instruction') - end + return t('doc_auth.info.verify_online_instruction_selfie') if selfie_required + return t('doc_auth.info.verify_online_instruction_mobile_no_selfie') if mobile_required + + t('doc_auth.info.verify_online_instruction') end def verify_online_description - if selfie_required - t('doc_auth.info.verify_online_description_selfie') + if mobile_required + t('doc_auth.info.verify_online_description_mobile') else t('doc_auth.info.verify_online_description') end end def submit - if selfie_required - t('forms.buttons.continue_remote_selfie') + if mobile_required + t('forms.buttons.continue_remote_mobile') else t('forms.buttons.continue_remote') end @@ -75,8 +75,8 @@ def post_office_instruction end def post_office_description - if selfie_required - t('doc_auth.info.verify_at_post_office_description_selfie') + if mobile_required + t('doc_auth.info.verify_at_post_office_description_mobile') else t('doc_auth.info.verify_at_post_office_description') end diff --git a/app/services/analytics_events.rb b/app/services/analytics_events.rb index d5f8016451d..8e867239b69 100644 --- a/app/services/analytics_events.rb +++ b/app/services/analytics_events.rb @@ -820,15 +820,32 @@ def gpo_confirmation_upload( # User visited sign-in URL from the "You've been successfully verified email" CTA button # @param issuer [String] the ServiceProvider.issuer # @param campaign_id [String] the email campaign ID + # @param [Hash,nil] proofing_components User's current proofing components + # @option proofing_components [String,nil] 'document_check' Vendor that verified the user's ID + # @option proofing_components [String,nil] 'document_type' Type of ID used to verify + # @option proofing_components [String,nil] 'source_check' Source used to verify user's PII + # @option proofing_components [String,nil] 'resolution_check' Vendor for identity resolution check + # @option proofing_components [String,nil] 'address_check' Method used to verify user's address + # @option proofing_components [Boolean,nil] 'threatmetrix' Whether ThreatMetrix check was done + # @option proofing_components [String,nil] 'threatmetrix_review_status' TMX decision on the user + # @param [String,nil] active_profile_idv_level ID verification level of user's active profile. + # @param [String,nil] pending_profile_idv_level ID verification level of user's pending profile. def idv_account_verified_cta_visited( issuer:, campaign_id:, + proofing_components: nil, + active_profile_idv_level: nil, + pending_profile_idv_level: nil, **extra ) track_event( :idv_account_verified_cta_visited, issuer:, campaign_id:, + proofing_components:, + active_profile_idv_level:, + pending_profile_idv_level:, + **extra, ) end @@ -1032,6 +1049,36 @@ def idv_barcode_warning_retake_photos_clicked(liveness_checking_required:, **ext ) end + # @param [String] initiating_service_provider The service provider the user needs to connect to + # The user chose not to connect their account from the SP follow-up page + def idv_by_mail_sp_follow_up_cancelled(initiating_service_provider:, **extra) + track_event( + :idv_by_mail_sp_follow_up_cancelled, + initiating_service_provider:, + **extra, + ) + end + + # @param [String] initiating_service_provider The service provider the user needs to connect to + # The user chose to connect their account from the SP follow-up page + def idv_by_mail_sp_follow_up_submitted(initiating_service_provider:, **extra) + track_event( + :idv_by_mail_sp_follow_up_submitted, + initiating_service_provider:, + **extra, + ) + end + + # @param [String] initiating_service_provider The service provider the user needs to connect to + # The user visited the SP follow-up page + def idv_by_mail_sp_follow_up_visited(initiating_service_provider:, **extra) + track_event( + :idv_by_mail_sp_follow_up_visited, + initiating_service_provider:, + **extra, + ) + end + # @param [Hash] error def idv_camera_info_error(error:, **_extra) track_event(:idv_camera_info_error, error: error) @@ -4682,6 +4729,76 @@ def idv_session_error_visited( ) end + # @param [Boolean] success Whether form validation was successful + # @param [Hash] errors Errors resulting from form validation + # @param [String] exception any exceptions thrown during request + # @param [String] docv_transaction_token socure transaction token + # @param [String] reference_id socure interal id for transaction + # @param [String] language lagnuage presented to user + # @param [String] step current step of idv to user + # @param [String] analytics_id id of analytics + # @param [Boolean] redo_document_capture if user is redoing doc capture + # @param [Boolean] skip_hybrid_handoff if user is skipping handoff + # @param [Boolean] selfie_check_required is selfie check required + # @param [Boolean] opted_in_to_in_person_proofing user opts in to IPP + # @param [Hash] redirect hash for redirect (url and method) + # @param [Hash] response_body hash received from socure + # @param ["hybrid","standard"] flow_path Document capture user flow + # @param [Float] vendor_request_time_in_ms Time it took to upload images & get a response. + # @param [Boolean] liveness_checking_required Whether or not the selfie is required + # @param [Boolean] liveness_enabled Whether or not the selfie result is included in response + # @param [String] vendor which 2rd party we are using for doc auth + # @param [Hash] document_type type of socument submitted (Drivers Licenese, etc.) + # The request for socure verification was sent + def idv_socure_document_request_submitted( + success:, + redirect:, + liveness_checking_required:, + vendor_request_time_in_ms:, + vendor:, + language:, + step:, + analytics_id:, + response_body:, + redo_document_capture: nil, + skip_hybrid_handoff: nil, + selfie_check_required: nil, + opted_in_to_in_person_proofing: nil, + errors: nil, + exception: nil, + reference_id: nil, + liveness_enabled: nil, + document_type: nil, + docv_transaction_token: nil, + flow_path: nil, + **extra + ) + track_event( + :idv_socure_document_request_submitted, + success:, + redirect:, + liveness_checking_required:, + vendor_request_time_in_ms:, + vendor:, + language:, + step:, + analytics_id:, + redo_document_capture:, + skip_hybrid_handoff:, + selfie_check_required:, + opted_in_to_in_person_proofing:, + errors:, + exception:, + reference_id:, + response_body:, + liveness_enabled:, + document_type:, + docv_transaction_token:, + flow_path:, + **extra, + ) + end + # Socure Reason Codes were downloaded and synced against persisted codes in the database # @param [Boolean] success Result from Socure KYC API call # @param [Hash] errors Result from resolution proofing diff --git a/app/services/doc_auth/socure/requests/document_request.rb b/app/services/doc_auth/socure/requests/document_request.rb index f214f8867c6..3fa0a99b10d 100644 --- a/app/services/doc_auth/socure/requests/document_request.rb +++ b/app/services/doc_auth/socure/requests/document_request.rb @@ -16,13 +16,6 @@ def initialize( @language = language end - private - - def lang(language) - return 'zh-cn' if language == :zh - language - end - def body redirect = { method: 'GET', @@ -40,6 +33,13 @@ def body }.to_json end + private + + def lang(language) + return 'zh-cn' if language == :zh + language + end + def handle_http_response(http_response) JSON.parse(http_response.body, symbolize_names: true) end diff --git a/app/services/doc_auth/socure/requests/docv_result_request.rb b/app/services/doc_auth/socure/requests/docv_result_request.rb index 7f4bc26d116..8a3662343a6 100644 --- a/app/services/doc_auth/socure/requests/docv_result_request.rb +++ b/app/services/doc_auth/socure/requests/docv_result_request.rb @@ -6,8 +6,13 @@ module Requests class DocvResultRequest < DocAuth::Socure::Request attr_reader :document_capture_session_uuid, :biometric_comparison_required - def initialize(document_capture_session_uuid:, biometric_comparison_required: false) + def initialize( + document_capture_session_uuid:, + docv_transaction_token_override: nil, + biometric_comparison_required: false + ) @document_capture_session_uuid = document_capture_session_uuid + @docv_transaction_token_override = docv_transaction_token_override @biometric_comparison_required = biometric_comparison_required end @@ -16,7 +21,7 @@ def initialize(document_capture_session_uuid:, biometric_comparison_required: fa def body { modules: ['documentverification'], - docvTransactionToken: document_capture_session.socure_docv_transaction_token, + docvTransactionToken: docv_transaction_token, }.to_json end @@ -60,6 +65,16 @@ def endpoint def metric_name 'socure_id_plus_document_verification' end + + def docv_transaction_token + if IdentityConfig.store.socure_docv_verification_data_test_mode && + IdentityConfig.store.socure_docv_verification_data_test_mode_tokens. + include?(@docv_transaction_token_override) + return @docv_transaction_token_override + end + + document_capture_session.socure_docv_transaction_token + end end end end diff --git a/app/services/idv/analytics_events_enhancer.rb b/app/services/idv/analytics_events_enhancer.rb index 810e933438d..2b713d57d8d 100644 --- a/app/services/idv/analytics_events_enhancer.rb +++ b/app/services/idv/analytics_events_enhancer.rb @@ -31,7 +31,6 @@ module AnalyticsEventsEnhancer idv_doc_auth_ssn_visited idv_doc_auth_submitted_image_upload_form idv_doc_auth_submitted_image_upload_vendor - idv_socure_verification_data_requested idv_doc_auth_submitted_pii_validation idv_doc_auth_verify_proofing_results idv_doc_auth_verify_submitted @@ -97,6 +96,8 @@ module AnalyticsEventsEnhancer idv_sdk_selfie_image_capture_opened idv_selfie_image_added idv_session_error_visited + idv_socure_document_request_submitted + idv_socure_verification_data_requested idv_threatmetrix_response_body idv_usps_auth_token_refresh_job_completed idv_usps_auth_token_refresh_job_network_error diff --git a/app/services/idv/session.rb b/app/services/idv/session.rb index 071ce403a80..f7f48f83add 100644 --- a/app/services/idv/session.rb +++ b/app/services/idv/session.rb @@ -105,6 +105,7 @@ def respond_to_missing?(method_sym, include_private) VALID_SESSION_ATTRIBUTES.include?(attr_name_sym) || super end + # @return [Profile] def create_profile_from_applicant_with_password( user_password, is_enhanced_ipp:, proofing_components: ) @@ -141,6 +142,8 @@ def create_profile_from_applicant_with_password( if profile.gpo_verification_pending? create_gpo_entry(profile_maker.pii_attributes, profile) end + + profile end def opt_in_param diff --git a/app/services/proofing/lexis_nexis/ddp/response_redacter.rb b/app/services/proofing/lexis_nexis/ddp/response_redacter.rb index 75dda7dc8cd..721a01738a4 100644 --- a/app/services/proofing/lexis_nexis/ddp/response_redacter.rb +++ b/app/services/proofing/lexis_nexis/ddp/response_redacter.rb @@ -152,7 +152,6 @@ class ResponseRedacter national_id_worst_score org_id policy - policy_details_api policy_engine_version policy_score page_time_on diff --git a/app/services/saml_request_validator.rb b/app/services/saml_request_validator.rb index d055f00c766..3364854d94e 100644 --- a/app/services/saml_request_validator.rb +++ b/app/services/saml_request_validator.rb @@ -3,8 +3,9 @@ class SamlRequestValidator include ActiveModel::Model - validate :cert_exists + validate :request_cert_exists validate :authorized_service_provider + validate :registered_cert_exists validate :authorized_authn_context validate :parsable_vtr validate :authorized_email_nameid_format @@ -72,7 +73,18 @@ def parsable_vtr end end - def cert_exists + def registered_cert_exists + # if there is no service provider, this error has already been added + return if service_provider.blank? + return if service_provider.certs.present? + + errors.add( + :service_provider, :no_cert_registered, + type: :no_cert_registered + ) + end + + def request_cert_exists if @blank_cert errors.add(:service_provider, :blank_cert_element_req, type: :blank_cert_element_req) end diff --git a/app/services/sp_return_url_resolver.rb b/app/services/sp_return_url_resolver.rb index dbed6e0f4b4..0e2f2e3bfd8 100644 --- a/app/services/sp_return_url_resolver.rb +++ b/app/services/sp_return_url_resolver.rb @@ -24,6 +24,10 @@ def homepage_url service_provider.return_to_sp_url end + def post_idv_follow_up_url + service_provider.post_idv_follow_up_url || homepage_url + end + private def inferred_redirect_url diff --git a/app/views/idv/by_mail/sp_follow_up/new.html.erb b/app/views/idv/by_mail/sp_follow_up/new.html.erb new file mode 100644 index 00000000000..972f905773c --- /dev/null +++ b/app/views/idv/by_mail/sp_follow_up/new.html.erb @@ -0,0 +1,24 @@ +<% self.title = @presenter.heading %> + +
+ <%= image_tag(asset_url('user-access.svg'), width: '280', height: '91', alt: '', aria: { hidden: true }) %> +

<%= @presenter.heading %>

+
+ +

<%= @presenter.body %>

+ +
+ <%= render ButtonComponent.new( + url: idv_sp_follow_up_connect_path, + big: true, + wide: true, + ).with_content(t('idv.by_mail.sp_follow_up.connect_account')) %> +
+
+ <%= render ButtonComponent.new( + url: idv_sp_follow_up_cancel_path, + big: true, + wide: true, + outline: true, + ).with_content(t('idv.by_mail.sp_follow_up.go_to_account')) %> +
diff --git a/app/views/idv/how_to_verify/show.html.erb b/app/views/idv/how_to_verify/show.html.erb index bb19ea1e96a..4c1ee1f7fa8 100644 --- a/app/views/idv/how_to_verify/show.html.erb +++ b/app/views/idv/how_to_verify/show.html.erb @@ -50,7 +50,7 @@ <%= f.label( :selection_remote, ) do %> - <% if @selfie_required %> + <% if @mobile_required %> <%= t('doc_auth.tips.mobile_phone_required') %> diff --git a/app/views/users/webauthn_platform_recommended/new.html.erb b/app/views/users/webauthn_platform_recommended/new.html.erb index a0e357ff886..534df7a338e 100644 --- a/app/views/users/webauthn_platform_recommended/new.html.erb +++ b/app/views/users/webauthn_platform_recommended/new.html.erb @@ -23,18 +23,19 @@
- <%= render ButtonComponent.new( + <%= render SubmitButtonComponent.new( url: webauthn_platform_recommended_url, method: :post, params: { add_method: true }, - big: true, full_width: true, class: 'margin-bottom-2', ).with_content(t('webauthn_platform_recommended.cta')) %> - <%= render ButtonComponent.new( + <%= render SubmitButtonComponent.new( url: webauthn_platform_recommended_url, method: :post, unstyled: true, + big: false, + wide: false, ).with_content(t('webauthn_platform_recommended.skip')) %>
diff --git a/config/application.yml.default b/config/application.yml.default index 86e01893ec2..549a443c771 100644 --- a/config/application.yml.default +++ b/config/application.yml.default @@ -385,6 +385,8 @@ sign_in_user_id_per_ip_max_attempts: 50 skip_encryption_allowed_list: '["urn:gov:gsa:SAML:2.0.profiles:sp:sso:dev", "urn:gov:gsa:SAML:2.0.profiles:sp:sso:int"]' socure_docv_document_request_endpoint: '' socure_docv_enabled: false +socure_docv_verification_data_test_mode: false +socure_docv_verification_data_test_mode_tokens: '[]' socure_docv_webhook_secret_key: '' socure_docv_webhook_secret_key_queue: '[]' socure_idplus_api_key: '' diff --git a/config/locales/en.yml b/config/locales/en.yml index 7593fbd2ff2..dddee2c7af2 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -616,7 +616,7 @@ doc_auth.headings.upload_from_phone: Use your phone to take photos doc_auth.headings.verify_at_post_office: Verify your identity at a Post Office doc_auth.headings.verify_identity: Verify your identity doc_auth.headings.verify_online: Verify your identity online -doc_auth.headings.verify_online_selfie: Verify your identity online using your phone +doc_auth.headings.verify_online_mobile: Verify your identity online using your phone doc_auth.headings.verify_with_phone: Verify your identity using your phone doc_auth.headings.welcome: Let’s verify your identity for %{sp_name} doc_auth.hybrid_flow_warning.explanation_html: You’re using %{app_name} to verify your identity for access to %{service_provider_name} and its services. @@ -637,7 +637,7 @@ doc_auth.info.exit.without_sp: Exit identity verification and go to your account doc_auth.info.getting_started_html: '%{sp_name} needs to make sure you are you — not someone pretending to be you. %{link_html}' doc_auth.info.getting_started_learn_more: Learn more about verifying your identity doc_auth.info.how_to_verify: You have the option to verify your identity online, or in person at a participating Post Office. -doc_auth.info.how_to_verify_selfie: You have the option to verify your identity online with your phone, or in person at a participating Post Office. +doc_auth.info.how_to_verify_mobile: You have the option to verify your identity online with your phone, or in person at a participating Post Office. doc_auth.info.how_to_verify_troubleshooting_options_header: Want to learn more about how to verify your identity? doc_auth.info.hybrid_handoff: We’ll collect information about you by reading your state‑issued ID. doc_auth.info.hybrid_handoff_ipp_html: 'Don’t have a mobile phone? You can verify your identity at a United States Post Office instead.' @@ -674,14 +674,15 @@ doc_auth.info.tag: Recommended doc_auth.info.upload_from_computer: Don’t have a phone? Upload photos of your ID from this computer. doc_auth.info.upload_from_phone: You won’t have to sign in again, and you’ll switch back to this computer after you take photos. Your mobile phone must have a camera and a web browser. doc_auth.info.verify_at_post_office_description: This option is better if you don’t have a phone to take photos of your ID. -doc_auth.info.verify_at_post_office_description_selfie: Choose this option if you don’t have a phone to take pictures. +doc_auth.info.verify_at_post_office_description_mobile: Choose this option if you don’t have a phone to take pictures. doc_auth.info.verify_at_post_office_instruction: You’ll enter your ID information online, and verify your identity in person at a participating Post Office. doc_auth.info.verify_at_post_office_instruction_selfie: You’ll enter your ID information online, and verify your identity in person at a participating Post Office. doc_auth.info.verify_at_post_office_link_text: Learn more about verifying in person doc_auth.info.verify_identity: We’ll ask for your ID, phone number, and other personal information to verify your identity against public records. doc_auth.info.verify_online_description: This option is better if you have a phone to take photos of your ID. -doc_auth.info.verify_online_description_selfie: Choose this option if you have a phone to take pictures. +doc_auth.info.verify_online_description_mobile: Choose this option if you have a phone to take pictures. doc_auth.info.verify_online_instruction: You’ll take photos of your ID to verify your identity fully online. Most users finish this process in one sitting. +doc_auth.info.verify_online_instruction_mobile_no_selfie: You’ll take photos of your ID using a phone. Most users finish this process in one sitting. doc_auth.info.verify_online_instruction_selfie: You’ll take photos of your ID and a photo of yourself using a phone. Most users finish this process in one sitting. doc_auth.info.verify_online_link_text: Learn more about verifying online doc_auth.info.you_entered: 'You entered:' @@ -765,6 +766,7 @@ errors.messages.invalid_recaptcha_token: We’re sorry, but your computer or net errors.messages.invalid_sms_number: The phone number entered doesn’t support text messaging. Try the Phone call option. errors.messages.invalid_voice_number: Invalid phone number. Check that you’ve entered the correct country code or area code. errors.messages.missing_field: Please fill in this field. +errors.messages.no_cert_registered: Your service provider does not have a certificate registered. errors.messages.no_pending_profile: No profile is waiting for verification errors.messages.not_a_number: is not a number errors.messages.otp_format: Enter your entire one-time code without spaces or special characters @@ -862,7 +864,7 @@ forms.buttons.confirm: Confirm forms.buttons.continue: Continue forms.buttons.continue_ipp: Continue in person forms.buttons.continue_remote: Continue online -forms.buttons.continue_remote_selfie: Continue on your phone +forms.buttons.continue_remote_mobile: Continue on your phone forms.buttons.delete: Delete forms.buttons.disable: Delete forms.buttons.edit: Edit @@ -1011,6 +1013,10 @@ idv.buttons.change_ssn_label: Update Social Security number idv.buttons.change_state_id_label: Update state ID idv.buttons.continue_plain: Continue idv.buttons.mail.send: Request a letter +idv.by_mail.sp_follow_up.body: Sign back in to %{service_provider} to connect your verified %{app_name} account and access services. +idv.by_mail.sp_follow_up.connect_account: Connect your account +idv.by_mail.sp_follow_up.go_to_account: Go to account +idv.by_mail.sp_follow_up.heading: Connect to %{service_provider} idv.cancel.actions.account_page: Go to account page idv.cancel.actions.exit: Exit %{app_name} idv.cancel.actions.keep_going: No, keep going diff --git a/config/locales/es.yml b/config/locales/es.yml index baffc5ec289..2b9ec65d8af 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -627,7 +627,7 @@ doc_auth.headings.upload_from_phone: Utilice su teléfono para tomar fotos doc_auth.headings.verify_at_post_office: Verifique su identidad en una oficina de correos doc_auth.headings.verify_identity: Verifique su identidad doc_auth.headings.verify_online: Verifique su identidad en línea -doc_auth.headings.verify_online_selfie: Verifique su identidad en línea con su teléfono +doc_auth.headings.verify_online_mobile: Verifique su identidad en línea con su teléfono doc_auth.headings.verify_with_phone: Verifique su identidad con su teléfono doc_auth.headings.welcome: Verifiquemos su identidad para %{sp_name} doc_auth.hybrid_flow_warning.explanation_html: Está utilizando %{app_name} para verificar su identidad y acceder a %{service_provider_name} y sus servicios. @@ -648,7 +648,7 @@ doc_auth.info.exit.without_sp: Salga de la verificación de identidad y vaya a l doc_auth.info.getting_started_html: '%{sp_name} necesita asegurarse de que se trata de usted y no de alguien que se hace pasar por usted. %{link_html}' doc_auth.info.getting_started_learn_more: Obtenga más información sobre la verificación de su identidad doc_auth.info.how_to_verify: Tiene la opción de verificar su identidad en línea, o en persona en una oficina de correos participante. -doc_auth.info.how_to_verify_selfie: Tiene la opción de verificar su identidad en línea con su teléfono, o en persona en una oficina de correos participante. +doc_auth.info.how_to_verify_mobile: Tiene la opción de verificar su identidad en línea con su teléfono, o en persona en una oficina de correos participante. doc_auth.info.how_to_verify_troubleshooting_options_header: ¿Desea obtener más información sobre cómo verificar su identidad? doc_auth.info.hybrid_handoff: Recopilaremos información sobre usted leyendo su identificación emitida por el estado. doc_auth.info.hybrid_handoff_ipp_html: '¿No tiene un teléfono móvil? Puede verificar su identidad en una oficina de correos de los Estados Unidos.' @@ -685,14 +685,15 @@ doc_auth.info.tag: Recomendado doc_auth.info.upload_from_computer: '¿No tiene un teléfono? Cargue fotos de su identificación desde esta computadora.' doc_auth.info.upload_from_phone: No tendrá que volver a iniciar sesión y volverá a esta computadora después de tomar las fotos. Su teléfono móvil debe tener una cámara y un navegador web. doc_auth.info.verify_at_post_office_description: Esta opción es mejor si no tiene un teléfono para tomar fotografías de su identificación. -doc_auth.info.verify_at_post_office_description_selfie: Elija esta opción si no tiene un teléfono para tomar fotografías. +doc_auth.info.verify_at_post_office_description_mobile: Elija esta opción si no tiene un teléfono para tomar fotografías. doc_auth.info.verify_at_post_office_instruction: Ingresará la información de su identificación en línea, y verificará su identidad en persona en una oficina de correos participante. doc_auth.info.verify_at_post_office_instruction_selfie: Ingresará la información de su identificación en línea, y verificará su identidad en persona en una oficina de correos participante. doc_auth.info.verify_at_post_office_link_text: Obtenga más información sobre la verificación en persona doc_auth.info.verify_identity: Le pediremos su identificación, número de teléfono y otros datos personales para verificar su identidad comparándola con los registros públicos. doc_auth.info.verify_online_description: Esta opción es mejor si tiene un teléfono para tomar fotografías de su identificación. -doc_auth.info.verify_online_description_selfie: Elija esta opción si tiene un teléfono para tomar fotografías. +doc_auth.info.verify_online_description_mobile: Elija esta opción si tiene un teléfono para tomar fotografías. doc_auth.info.verify_online_instruction: Tomará fotografías de su identificación para verificar su identidad por completo en línea. La mayoría de los usuarios logran terminar este proceso en una sola sesión. +doc_auth.info.verify_online_instruction_mobile_no_selfie: Tomará fotografías de su identificación con un teléfono. La mayoría de los usuarios logran terminar este proceso en una sola sesión. doc_auth.info.verify_online_instruction_selfie: Tomará con un teléfono fotos de su identificación y una foto de usted. La mayoría de los usuarios logran terminar este proceso en una sola sesión. doc_auth.info.verify_online_link_text: Obtenga más información sobre la verificación en línea doc_auth.info.you_entered: 'Usted ingresó:' @@ -776,6 +777,7 @@ errors.messages.invalid_recaptcha_token: Lo sentimos, pero es posible que tu com errors.messages.invalid_sms_number: El número de teléfono ingresado no admite mensajes de texto. Intente la opción de llamada telefónica. errors.messages.invalid_voice_number: Número de teléfono no válido. Verifique haber ingresado el código de país o de área correcto. errors.messages.missing_field: Llene este campo. +errors.messages.no_cert_registered: No podemos detectar un certificado en su solicitud. errors.messages.no_pending_profile: No hay ningún perfil en espera de verificación errors.messages.not_a_number: no es un número errors.messages.otp_format: Ingrese su código de un solo uso completo, sin espacios ni caracteres especiales. @@ -873,7 +875,7 @@ forms.buttons.confirm: Confirmar forms.buttons.continue: Continuar forms.buttons.continue_ipp: Continúe en persona forms.buttons.continue_remote: Continúe en línea -forms.buttons.continue_remote_selfie: Continúe en su teléfono +forms.buttons.continue_remote_mobile: Continúe en su teléfono forms.buttons.delete: Eliminar forms.buttons.disable: Eliminar forms.buttons.edit: Editar @@ -1022,6 +1024,10 @@ idv.buttons.change_ssn_label: Actualizar número de Seguro Social idv.buttons.change_state_id_label: Actualizar identificación estatal idv.buttons.continue_plain: Continuar idv.buttons.mail.send: Solicitar una carta +idv.by_mail.sp_follow_up.body: Vuelva a iniciar sesión en %{service_provider} para conectar su cuenta verificada de %{app_name} y acceder a los servicios. +idv.by_mail.sp_follow_up.connect_account: Conecte su cuenta +idv.by_mail.sp_follow_up.go_to_account: Ir a la cuenta +idv.by_mail.sp_follow_up.heading: Conéctese a %{service_provider} idv.cancel.actions.account_page: Ir a la página de la cuenta idv.cancel.actions.exit: Salir de %{app_name} idv.cancel.actions.keep_going: No, continuar diff --git a/config/locales/fr.yml b/config/locales/fr.yml index dc2ae99a5ed..1e7ef47f685 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -616,7 +616,7 @@ doc_auth.headings.upload_from_phone: Utiliser votre téléphone pour prendre des doc_auth.headings.verify_at_post_office: Confirmer votre identité en personne dans un bureau de poste doc_auth.headings.verify_identity: Confirmer votre identité doc_auth.headings.verify_online: Confirmer votre identité en ligne -doc_auth.headings.verify_online_selfie: Confirmer votre identité en ligne à l’aide de votre téléphone +doc_auth.headings.verify_online_mobile: Confirmer votre identité en ligne à l’aide de votre téléphone doc_auth.headings.verify_with_phone: Confirmer votre identité à l’aide de votre téléphone doc_auth.headings.welcome: Vérifions votre identité auprès de %{sp_name} doc_auth.hybrid_flow_warning.explanation_html: Vous utilisez %{app_name} pour confirmer votre identité et accéder à %{service_provider_name} et à ses services. @@ -637,7 +637,7 @@ doc_auth.info.exit.without_sp: Quitter la vérification d’identité et accéde doc_auth.info.getting_started_html: '%{sp_name} doit s’assurer qu’il s’agit bien de vous et non de quelqu’un qui se fait passer pour vous. %{link_html}' doc_auth.info.getting_started_learn_more: En savoir plus sur la vérification de votre identité doc_auth.info.how_to_verify: Vous pouvez confirmer votre identité en ligne ou en personne dans un bureau de poste participant. -doc_auth.info.how_to_verify_selfie: Vous avez la possibilité de confirmer votre identité en ligne avec votre téléphone ou en personne dans un bureau de poste participant. +doc_auth.info.how_to_verify_mobile: Vous avez la possibilité de confirmer votre identité en ligne avec votre téléphone ou en personne dans un bureau de poste participant. doc_auth.info.how_to_verify_troubleshooting_options_header: Vous voulez en savoir plus sur la façon de confirmer votre identité? doc_auth.info.hybrid_handoff: Nous recueillerons des informations vous concernant en lisant votre pièce d’identité délivrée par un État. doc_auth.info.hybrid_handoff_ipp_html: 'Vous n’avez pas de téléphone portable? Vous pouvez confirmer votre identité dans un bureau de poste américain participant.' @@ -674,14 +674,15 @@ doc_auth.info.tag: Recommandation doc_auth.info.upload_from_computer: Vous n’avez pas de téléphone ? Téléchargez les photos de votre pièce d’identité depuis cet ordinateur. doc_auth.info.upload_from_phone: Vous n’aurez pas à vous reconnecter. Vous reviendrez sur cet ordinateur après avoir pris des photos. Votre téléphone portable doit être équipé d’un appareil photo et d’un navigateur web. doc_auth.info.verify_at_post_office_description: Cette option est préférable si vous n’avez pas de téléphone permettant de prendre des photos de votre pièce d’identité. -doc_auth.info.verify_at_post_office_description_selfie: Choisissez cette option si vous ne disposez pas d’un téléphone permettant de prendre des photos. +doc_auth.info.verify_at_post_office_description_mobile: Choisissez cette option si vous ne disposez pas d’un téléphone permettant de prendre des photos. doc_auth.info.verify_at_post_office_instruction: Vous saisirez vos données d’identification en ligne et confirmerez votre identité en personne dans un bureau de poste participant. doc_auth.info.verify_at_post_office_instruction_selfie: Vous saisirez vos données d’identification en ligne et confirmez votre identité en personne dans un bureau de poste participant. doc_auth.info.verify_at_post_office_link_text: En savoir plus sur la vérification en personne doc_auth.info.verify_identity: Nous vous demanderons votre pièce d’identité, numéro de téléphone et d’autres renseignements personnels afin de confirmer votre identité par rapport aux registres publics. doc_auth.info.verify_online_description: Cette option est préférable si vous disposez d’un téléphone permettant de prendre des photos de votre pièce d’identité. -doc_auth.info.verify_online_description_selfie: Choisissez cette option si vous disposez d’un téléphone permettant de prendre des photos. +doc_auth.info.verify_online_description_mobile: Choisissez cette option si vous disposez d’un téléphone permettant de prendre des photos. doc_auth.info.verify_online_instruction: Vous prendrez des photos de votre pièce d’identité pour confirmer votre identité entièrement en ligne. La plupart des utilisateurs y parviennent en une seule prise. +doc_auth.info.verify_online_instruction_mobile_no_selfie: Vous prendrez des photos de votre pièce d’identité à l’aide d’un téléphone. La plupart des utilisateurs effectuent l’ensemble du processus en une seule fois. doc_auth.info.verify_online_instruction_selfie: Vous prendrez des photos de votre pièce d’identité et une photo de vous-même avec un téléphone. La plupart des utilisateurs y parviennent en une seule prise. doc_auth.info.verify_online_link_text: En savoir plus sur la vérification en ligne doc_auth.info.you_entered: 'Vous avez saisi :' @@ -765,6 +766,7 @@ errors.messages.invalid_recaptcha_token: Désolé, il est possible que votre ord errors.messages.invalid_sms_number: Le numéro de téléphone saisi ne prend pas en charge les messages texte. Veuillez essayer l’option d’appel téléphonique. errors.messages.invalid_voice_number: Numéro de téléphone non valide. Vérifiez que vous avez entré le bon indicatif international ou régional. errors.messages.missing_field: Veuillez remplir ce champ. +errors.messages.no_cert_registered: Nous ne pouvons pas détecter un certificat sur votre demande. errors.messages.no_pending_profile: Aucun profil en attente de vérification errors.messages.not_a_number: n’est pas un chiffre errors.messages.otp_format: Saisissez l’intégralité de votre code à usage unique sans espaces ni caractères spéciaux @@ -862,7 +864,7 @@ forms.buttons.confirm: Confirmer forms.buttons.continue: Suite forms.buttons.continue_ipp: Continuer en personne forms.buttons.continue_remote: Continuer en ligne -forms.buttons.continue_remote_selfie: Continuer sur votre téléphone +forms.buttons.continue_remote_mobile: Continuer sur votre téléphone forms.buttons.delete: Supprimer forms.buttons.disable: Supprimer forms.buttons.edit: Modifier @@ -1011,6 +1013,10 @@ idv.buttons.change_ssn_label: Mettre à jour votre numéro de sécurité sociale idv.buttons.change_state_id_label: Mettre à jour votre pièce d’identité idv.buttons.continue_plain: Suite idv.buttons.mail.send: Demander une lettre +idv.by_mail.sp_follow_up.body: Connectez-vous à nouveau à %{service_provider} pour y associer votre compte %{app_name} vérifié et accéder aux services de cet organisme. +idv.by_mail.sp_follow_up.connect_account: Associer votre compte +idv.by_mail.sp_follow_up.go_to_account: Aller sur le compte +idv.by_mail.sp_follow_up.heading: Vous connecter à %{service_provider} idv.cancel.actions.account_page: Aller à la page de votre compte idv.cancel.actions.exit: Quitter %{app_name} idv.cancel.actions.keep_going: Non, continuer diff --git a/config/locales/zh.yml b/config/locales/zh.yml index ea75d8f839a..d4727ee6bf5 100644 --- a/config/locales/zh.yml +++ b/config/locales/zh.yml @@ -627,7 +627,7 @@ doc_auth.headings.upload_from_phone: 使用手机拍照 doc_auth.headings.verify_at_post_office: 去邮局验证身份 doc_auth.headings.verify_identity: 验证你的身份 doc_auth.headings.verify_online: 在网上验证身份 -doc_auth.headings.verify_online_selfie: 使用手机在网上验证你的身份 +doc_auth.headings.verify_online_mobile: 使用手机在网上验证你的身份 doc_auth.headings.verify_with_phone: 使用你的电话来验证你的身份 doc_auth.headings.welcome: 现在我们来为%{sp_name}验证你的身份 doc_auth.hybrid_flow_warning.explanation_html: 你在使用 %{app_name} 验证身份以访问 %{service_provider_name} 及其服务。 @@ -648,7 +648,7 @@ doc_auth.info.exit.without_sp: 退出身份验证并到你的账户页面 doc_auth.info.getting_started_html: '%{sp_name} 需要确保你是你,而不是别人冒充你。 了解更多有关验证你身份的信息 %{link_html}' doc_auth.info.getting_started_learn_more: 了解有关验证你身份的更多信息 doc_auth.info.how_to_verify: 你可以选择在网上验证身份或者到参与本项目的邮局亲身验证身份。 -doc_auth.info.how_to_verify_selfie: 你可以选择用你的手机在网上验证身份或者到参与本项目的邮局亲身验证身份。 +doc_auth.info.how_to_verify_mobile: 你可以选择用你的手机在网上验证身份或者到参与本项目的邮局亲身验证身份。 doc_auth.info.how_to_verify_troubleshooting_options_header: 想对验证身份获得更多了解吗? doc_auth.info.hybrid_handoff: 我们将通过读取州政府颁发给你的身份证件来收集你的信息。 doc_auth.info.hybrid_handoff_ipp_html: '没有手机?你可以去一个美国邮局验证身份。' @@ -685,14 +685,15 @@ doc_auth.info.tag: 建议 doc_auth.info.upload_from_computer: 没有手机?从该电脑上传你身份证件的照片。 doc_auth.info.upload_from_phone: 你不必重新登录,而且拍完照后可以转回到该电脑。你的手机必须带有相机和网络浏览器。 doc_auth.info.verify_at_post_office_description: 如果你没有手机拍身份证件照片,这一选项更好。 -doc_auth.info.verify_at_post_office_description_selfie: 如果你没有手机可以拍照,请选择该选项 +doc_auth.info.verify_at_post_office_description_mobile: 如果你没有手机可以拍照,请选择该选项 doc_auth.info.verify_at_post_office_instruction: 你在网上输入身份证件信息,然后到一个参与本项目的邮局去亲身验证身份。 doc_auth.info.verify_at_post_office_instruction_selfie: 你在网上输入身份证件信息,然后到一个参与本项目的邮局去亲身验证身份。 doc_auth.info.verify_at_post_office_link_text: 对亲身验证获得更多了解 doc_auth.info.verify_identity: 我们会要求获得你的身份识别、电话号码和其他个人信息并通过与公共记录核对来验证你的身份。 doc_auth.info.verify_online_description: 如果你没有移动设备或者无法轻松拍身份证件照片,这一选项更好。 -doc_auth.info.verify_online_description_selfie: 如果你有手机可以拍照,请选择该选项。 +doc_auth.info.verify_online_description_mobile: 如果你有手机可以拍照,请选择该选项。 doc_auth.info.verify_online_instruction: 你将拍身份证件的照片来完全在网上验证身份。大多数用户都能轻松完成这样流程。 +doc_auth.info.verify_online_instruction_mobile_no_selfie: 你将使用手机拍摄你的身份证件照片。大多数用户一次就能完成这个流程。 doc_auth.info.verify_online_instruction_selfie: 你将用手机拍摄身份证件和本人的照片。大多数用户都能轻松完成这一流程。 doc_auth.info.verify_online_link_text: 对网上验证获得更多了解 doc_auth.info.you_entered: 你输入了: @@ -776,6 +777,7 @@ errors.messages.invalid_recaptcha_token: 你必须完成预防滥发邮件测验 errors.messages.invalid_sms_number: 输入的电话号码不支持短信。尝试接听电话选项。 errors.messages.invalid_voice_number: 电话号码有误。检查一下你是否输入了正确的国家代码或区域代码。 errors.messages.missing_field: 请填写这一字段。 +errors.messages.no_cert_registered: 我们在你的请求中探查不到证书。 errors.messages.no_pending_profile: 没有等待验证的用户资料 errors.messages.not_a_number: 不是数字 errors.messages.otp_format: 输入你完整的一次性代码(没有空白或特殊字符) @@ -873,7 +875,7 @@ forms.buttons.confirm: 确认 forms.buttons.continue: 继续 forms.buttons.continue_ipp: 继续亲身验证 forms.buttons.continue_remote: 继续在网上验证 -forms.buttons.continue_remote_selfie: 在手机上继续 +forms.buttons.continue_remote_mobile: 在手机上继续 forms.buttons.delete: 删除 forms.buttons.disable: 删除 forms.buttons.edit: 编辑 @@ -1024,6 +1026,10 @@ idv.buttons.change_ssn_label: 更新社会保障号码 idv.buttons.change_state_id_label: 更新州颁发的身份证件 idv.buttons.continue_plain: 继续 idv.buttons.mail.send: 要求发一封信 +idv.by_mail.sp_follow_up.body: 重新登录 %{service_provider}以连接你验证过的%{app_name}账户并获得服务。 +idv.by_mail.sp_follow_up.connect_account: 连接你的账户 +idv.by_mail.sp_follow_up.go_to_account: 前往账户 +idv.by_mail.sp_follow_up.heading: 连接 %{service_provider} idv.cancel.actions.account_page: 到账户页面 idv.cancel.actions.exit: 退出 %{app_name} idv.cancel.actions.keep_going: 不是,继续 diff --git a/config/routes.rb b/config/routes.rb index f30ff1f5936..78c4010b282 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -451,6 +451,9 @@ end get '/by_mail/letter_enqueued' => 'by_mail/letter_enqueued#show', as: :letter_enqueued + get '/by_mail/sp_follow_up' => 'by_mail/sp_follow_up#new', as: :sp_follow_up + get '/by_mail/sp_follow_up/connect' => 'by_mail/sp_follow_up#show', as: :sp_follow_up_connect + get '/by_mail/sp_follow_up/cancel' => 'by_mail/sp_follow_up#cancel', as: :sp_follow_up_cancel # We re-mapped `/verify/by_mail` to `/verify/by_mail/enter_code`. However, we sent emails to # users with a link to `/verify/by_mail?did_not_receive_letter=1`. We need to continue diff --git a/config/service_providers.localdev.yml b/config/service_providers.localdev.yml index 9b905e8ad0f..2a69dd342e1 100644 --- a/config/service_providers.localdev.yml +++ b/config/service_providers.localdev.yml @@ -217,6 +217,7 @@ test: assertion_consumer_logout_service_url: '' ial: 2 allow_prompt_login: true + post_idv_follow_up_url: http://localhost/post_idv_follow_up_url 'urn:gov:gsa:openidconnect:sp:server_ial1': agency_id: 2 diff --git a/db/primary_migrate/20241203163014_add_post_idv_follow_up_url_to_service_provider.rb b/db/primary_migrate/20241203163014_add_post_idv_follow_up_url_to_service_provider.rb new file mode 100644 index 00000000000..44440e44430 --- /dev/null +++ b/db/primary_migrate/20241203163014_add_post_idv_follow_up_url_to_service_provider.rb @@ -0,0 +1,5 @@ +class AddPostIdvFollowUpUrlToServiceProvider < ActiveRecord::Migration[7.2] + def change + add_column :service_providers, :post_idv_follow_up_url, :string, comment: 'sensitive=false' + end +end diff --git a/db/schema.rb b/db/schema.rb index 0c4f93cf8d4..135f2b0231c 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.2].define(version: 2024_11_15_215510) do +ActiveRecord::Schema[7.2].define(version: 2024_12_03_163014) do # These are extensions that must be enabled in order to support this database enable_extension "citext" enable_extension "pg_stat_statements" @@ -551,6 +551,7 @@ t.boolean "use_legacy_name_id_behavior", default: false, comment: "sensitive=false" t.boolean "irs_attempts_api_enabled", comment: "sensitive=false" t.boolean "in_person_proofing_enabled", default: false, comment: "sensitive=false" + t.string "post_idv_follow_up_url", comment: "sensitive=false" t.index ["issuer"], name: "index_service_providers_on_issuer", unique: true end diff --git a/lib/identity_config.rb b/lib/identity_config.rb index b66644e7792..cd90324d7ed 100644 --- a/lib/identity_config.rb +++ b/lib/identity_config.rb @@ -421,6 +421,8 @@ def self.store config.add(:recommend_webauthn_platform_for_sms_ab_test_authentication_percent, type: :integer) config.add(:socure_docv_document_request_endpoint, type: :string) config.add(:socure_docv_enabled, type: :boolean) + config.add(:socure_docv_verification_data_test_mode, type: :boolean) + config.add(:socure_docv_verification_data_test_mode_tokens, type: :json) config.add(:socure_docv_webhook_secret_key_queue, type: :json) config.add(:socure_docv_webhook_secret_key, type: :string) config.add(:socure_idplus_api_key, type: :string) diff --git a/lib/reporting/protocols_report.rb b/lib/reporting/protocols_report.rb index fe1d333961a..560d7da79d7 100644 --- a/lib/reporting/protocols_report.rb +++ b/lib/reporting/protocols_report.rb @@ -17,6 +17,7 @@ class ProtocolsReport attr_reader :time_range SAML_AUTH_EVENT = 'SAML Auth' + SAML_AUTH_REQUEST_EVENT = 'SAML Auth Request' OIDC_AUTH_EVENT = 'OpenID Connect: authorization request' # @param [Range