diff --git a/app/controllers/two_factor_authentication/totp_verification_controller.rb b/app/controllers/two_factor_authentication/totp_verification_controller.rb index 5eacc1d413f..e7cdd499a03 100644 --- a/app/controllers/two_factor_authentication/totp_verification_controller.rb +++ b/app/controllers/two_factor_authentication/totp_verification_controller.rb @@ -9,7 +9,10 @@ def show @presenter = presenter_for_two_factor_authentication_method return unless FeatureManagement.prefill_otp_codes? - @code = ROTP::TOTP.new(current_user.auth_app_configurations.first.otp_secret_key).now + @code = ROTP::TOTP.new( + current_user.auth_app_configurations.first.otp_secret_key, + interval: IdentityConfig.store.totp_code_interval, + ).now end def create diff --git a/app/decorators/user_decorator.rb b/app/decorators/user_decorator.rb index b709f1af0ec..bc127eee8ad 100644 --- a/app/decorators/user_decorator.rb +++ b/app/decorators/user_decorator.rb @@ -82,6 +82,7 @@ def qrcode(otp_secret_key) issuer: 'Login.gov', otp_secret_key: otp_secret_key, digits: TwoFactorAuthenticatable::DIRECT_OTP_LENGTH, + interval: IdentityConfig.store.totp_code_interval, } url = ROTP::TOTP.new(otp_secret_key, options).provisioning_uri(email) qrcode = RQRCode::QRCode.new(url) diff --git a/app/services/db/auth_app_configuration.rb b/app/services/db/auth_app_configuration.rb index fc0dc99e0cc..b2d9f5c3170 100644 --- a/app/services/db/auth_app_configuration.rb +++ b/app/services/db/auth_app_configuration.rb @@ -11,7 +11,11 @@ def self.create(user, otp_secret_key, totp_timestamp, name = Time.zone.now.to_s) def self.authenticate(user, code) user.auth_app_configurations.each do |cfg| - totp = ROTP::TOTP.new(cfg.otp_secret_key, digits: TwoFactorAuthenticatable::OTP_LENGTH) + totp = ROTP::TOTP.new( + cfg.otp_secret_key, + digits: TwoFactorAuthenticatable::OTP_LENGTH, + interval: IdentityConfig.store.totp_code_interval, + ) new_timestamp = totp.verify( code, drift_ahead: TwoFactorAuthenticatable::ALLOWED_OTP_DRIFT_SECONDS, @@ -24,7 +28,11 @@ def self.authenticate(user, code) end def self.confirm(secret, code) - totp = ROTP::TOTP.new(secret, digits: TwoFactorAuthenticatable::DIRECT_OTP_LENGTH) + totp = ROTP::TOTP.new( + secret, + digits: TwoFactorAuthenticatable::DIRECT_OTP_LENGTH, + interval: IdentityConfig.store.totp_code_interval, + ) totp.verify( code, drift_ahead: TwoFactorAuthenticatable::ALLOWED_OTP_DRIFT_SECONDS, drift_behind: TwoFactorAuthenticatable::ALLOWED_OTP_DRIFT_SECONDS diff --git a/config/application.yml.default b/config/application.yml.default index 82cf75366b2..6de979f63b9 100644 --- a/config/application.yml.default +++ b/config/application.yml.default @@ -237,6 +237,7 @@ sp_context_needed_environment: 'prod' sp_handoff_bounce_max_seconds: 2 show_user_attribute_deprecation_warnings: false test_ssn_allowed_list: '' +totp_code_interval: 30 unauthorized_scope_enabled: false usps_upload_enabled: false usps_upload_sftp_timeout: 5 @@ -491,6 +492,7 @@ test: state_tracking_enabled: true telephony_adapter: test test_ssn_allowed_list: '999999999' + totp_code_interval: 3 verify_gpo_key_attempt_window_in_minutes: 3 verify_gpo_key_max_attempts: 2 verify_personal_key_attempt_window_in_minutes: 3 diff --git a/lib/identity_config.rb b/lib/identity_config.rb index 542d18c5d6c..53e39551468 100644 --- a/lib/identity_config.rb +++ b/lib/identity_config.rb @@ -332,6 +332,7 @@ def self.build_store(config_map) config.add(:state_tracking_enabled, type: :boolean) config.add(:telephony_adapter, type: :string) config.add(:test_ssn_allowed_list, type: :comma_separated_string_list) + config.add(:totp_code_interval, type: :integer) config.add(:unauthorized_scope_enabled, type: :boolean) config.add(:use_dashboard_service_providers, type: :boolean) config.add(:use_kms, type: :boolean) diff --git a/spec/support/otp_helper.rb b/spec/support/otp_helper.rb index 1efd19c7712..0268910265b 100644 --- a/spec/support/otp_helper.rb +++ b/spec/support/otp_helper.rb @@ -17,4 +17,11 @@ def last_phone_otp end nil end + + def last_totp(user) + ROTP::TOTP.new( + user.auth_app_configurations.first.otp_secret_key, + interval: IdentityConfig.store.totp_code_interval, + ).now + end end diff --git a/spec/support/totp_helper.rb b/spec/support/totp_helper.rb index 644383cc247..a6c40ba943d 100644 --- a/spec/support/totp_helper.rb +++ b/spec/support/totp_helper.rb @@ -1,3 +1,3 @@ def generate_totp_code(secret) - ROTP::TOTP.new(secret).at(Time.zone.now) + ROTP::TOTP.new(secret, interval: IdentityConfig.store.totp_code_interval).at(Time.zone.now) end