diff --git a/app/jobs/usps_auth_token_refresh_job.rb b/app/jobs/usps_auth_token_refresh_job.rb new file mode 100644 index 00000000000..220fe7db19e --- /dev/null +++ b/app/jobs/usps_auth_token_refresh_job.rb @@ -0,0 +1,30 @@ +class UspsAuthTokenRefreshJob < ApplicationJob + queue_as :default + + def perform + analytics.idv_usps_auth_token_refresh_job_started + + usps_proofer.retrieve_token! + ensure + analytics.idv_usps_auth_token_refresh_job_completed + end + + private + + def usps_proofer + if IdentityConfig.store.usps_mock_fallback + UspsInPersonProofing::Mock::Proofer.new + else + UspsInPersonProofing::Proofer.new + end + end + + def analytics + @analytics ||= Analytics.new( + user: AnonymousUser.new, + request: nil, + session: {}, + sp: nil, + ) + end +end diff --git a/app/services/analytics_events.rb b/app/services/analytics_events.rb index 2c572f06e34..36d09b33dab 100644 --- a/app/services/analytics_events.rb +++ b/app/services/analytics_events.rb @@ -2209,6 +2209,22 @@ def idv_start_over( ) end + # Track when USPS auth token refresh job completed + def idv_usps_auth_token_refresh_job_completed(**extra) + track_event( + 'UspsAuthTokenRefreshJob: Completed', + **extra, + ) + end + + # Track when USPS auth token refresh job started + def idv_usps_auth_token_refresh_job_started(**extra) + track_event( + 'UspsAuthTokenRefreshJob: Started', + **extra, + ) + end + # @param [String] flow_path Document capture path ("hybrid" or "standard") # The user clicked the troubleshooting option to start in-person proofing def idv_verify_in_person_troubleshooting_option_clicked(flow_path:, diff --git a/config/application.yml.default b/config/application.yml.default index 97e7596956f..c428faaddfa 100644 --- a/config/application.yml.default +++ b/config/application.yml.default @@ -330,6 +330,7 @@ verify_personal_key_max_attempts: 5 version_headers_enabled: false use_dashboard_service_providers: false use_kms: false +usps_auth_token_refresh_job_enabled: false usps_confirmation_max_days: 10 usps_ipp_password: '' usps_ipp_client_id: '' @@ -481,6 +482,7 @@ production: state_tracking_enabled: false telephony_adapter: pinpoint use_kms: true + usps_auth_token_refresh_job_enabled: true usps_confirmation_max_days: 30 usps_upload_sftp_directory: '' usps_upload_sftp_host: '' diff --git a/config/initializers/job_configurations.rb b/config/initializers/job_configurations.rb index 03e3143d4c4..8cf01a96956 100644 --- a/config/initializers/job_configurations.rb +++ b/config/initializers/job_configurations.rb @@ -1,4 +1,5 @@ cron_5m = '0/5 * * * *' +cron_12m = '0/12 * * * *' cron_1h = '0 * * * *' cron_24h = '0 0 * * *' gpo_cron_24h = '0 10 * * *' # 10am UTC is 5am EST/6am EDT @@ -163,6 +164,12 @@ cron: cron_24h, args: -> { [Time.zone.yesterday] }, }, + usps_auth_token_refresh: (if IdentityConfig.store.usps_auth_token_refresh_job_enabled + { + class: 'UspsAuthTokenRefreshJob', + cron: cron_12m, + } + end), arcgis_token: (if IdentityConfig.store.arcgis_api_refresh_token_job_enabled { class: 'ArcgisTokenJob', diff --git a/lib/identity_config.rb b/lib/identity_config.rb index 1a1970553d8..27a1d873a69 100644 --- a/lib/identity_config.rb +++ b/lib/identity_config.rb @@ -429,6 +429,7 @@ def self.build_store(config_map) config.add(:unauthorized_scope_enabled, type: :boolean) config.add(:use_dashboard_service_providers, type: :boolean) config.add(:use_kms, type: :boolean) + config.add(:usps_auth_token_refresh_job_enabled, type: :boolean) config.add(:usps_mock_fallback, type: :boolean) config.add(:usps_confirmation_max_days, type: :integer) config.add(:usps_ipp_password, type: :string) diff --git a/spec/jobs/usps_auth_token_refresh_job_spec.rb b/spec/jobs/usps_auth_token_refresh_job_spec.rb new file mode 100644 index 00000000000..07f39be9982 --- /dev/null +++ b/spec/jobs/usps_auth_token_refresh_job_spec.rb @@ -0,0 +1,85 @@ +require 'rails_helper' + +RSpec.describe UspsAuthTokenRefreshJob, type: :job do + include UspsIppHelper + + let(:subject) { described_class.new } + let(:root_url) { 'http://my.root.url' } + let(:analytics) { instance_double(Analytics) } + let(:usps_auth_token_cache_key) { UspsInPersonProofing::Proofer::AUTH_TOKEN_CACHE_KEY } + + before do + allow(IdentityConfig.store).to receive(:usps_ipp_root_url).and_return(root_url) + + allow(Analytics).to receive(:new). + with( + user: an_instance_of(AnonymousUser), + request: nil, + session: {}, + sp: nil, + ).and_return(analytics) + end + + describe 'usps auth token refresh job' do + context 'when using redis as a backing store' do + before do |ex| + allow(Rails).to receive(:cache).and_return( + ActiveSupport::Cache::RedisCacheStore.new(url: IdentityConfig.store.redis_throttle_url), + ) + end + + it 'requests and sets a new token in the cache' do + # rubocop:disable Layout/LineLength + new_token_value = '==PZWyMP2ZHGOIeTd17YomIf7XjZUL4G93dboY1pTsuTJN0s9BwMYvOcIS9B3gRvloK2sroi9uFXdXrFuly7==' + # rubocop:enable Layout/LineLength + stub_request_token + + expect(analytics).to receive( + :idv_usps_auth_token_refresh_job_started, + ).once + expect(analytics).to receive( + :idv_usps_auth_token_refresh_job_completed, + ).once + + expect(Rails.cache).to receive(:write).with( + usps_auth_token_cache_key, + an_instance_of(String), + hash_including(expires_in: an_instance_of(ActiveSupport::Duration)), + ).and_call_original + + subject.perform + + expect(WebMock).to have_requested(:post, "#{root_url}/oauth/authenticate") + expect(Rails.cache.fetch(usps_auth_token_cache_key)).to eq("Bearer #{new_token_value}") + end + + it 'manually sets the expiration' do + allow(analytics).to receive(:idv_usps_auth_token_refresh_job_started) + allow(analytics).to receive(:idv_usps_auth_token_refresh_job_completed) + + stub_request_token + subject.perform + + ttl = Rails.cache.redis.ttl(usps_auth_token_cache_key) + expect(ttl).to be > 0 + end + end + + context 'auth request throws error' do + it 'still logs analytics' do + stub_error_request_token + + expect(analytics).to receive( + :idv_usps_auth_token_refresh_job_started, + ).once + expect(analytics).to receive( + :idv_usps_auth_token_refresh_job_completed, + ).once + + expect do + subject.perform + end.to raise_error + end + end + end +end diff --git a/spec/support/usps_ipp_helper.rb b/spec/support/usps_ipp_helper.rb index df12caf71d6..07fd3497a40 100644 --- a/spec/support/usps_ipp_helper.rb +++ b/spec/support/usps_ipp_helper.rb @@ -15,6 +15,14 @@ def stub_request_token ) end + def stub_error_request_token + stub_request(:post, %r{/oauth/authenticate}).to_return( + status: 500, + body: [], + headers: { 'content-type' => 'application/json' }, + ) + end + def stub_request_facilities stub_request(:post, %r{/ivs-ippaas-api/IPPRest/resources/rest/getIppFacilityList}).to_return( status: 200,