diff --git a/app/controllers/concerns/two_factor_authenticatable.rb b/app/controllers/concerns/two_factor_authenticatable.rb index df550e7fdcd..6f5ff8542d6 100644 --- a/app/controllers/concerns/two_factor_authenticatable.rb +++ b/app/controllers/concerns/two_factor_authenticatable.rb @@ -13,9 +13,9 @@ module TwoFactorAuthenticatable def handle_second_factor_locked_user analytics.track_event(Analytics::MULTI_FACTOR_AUTH_MAX_ATTEMPTS) - render 'two_factor_authentication/shared/max_login_attempts_reached' - sign_out + + render 'two_factor_authentication/shared/max_login_attempts_reached' end def check_already_authenticated diff --git a/app/views/layouts/application.html.slim b/app/views/layouts/application.html.slim index ad640332295..8ac7ed4c9b5 100644 --- a/app/views/layouts/application.html.slim +++ b/app/views/layouts/application.html.slim @@ -50,7 +50,7 @@ html lang="#{I18n.locale}" = render 'shared/footer_lite' #session-timeout-cntnr - - if user_fully_authenticated? + - if current_user = auto_session_timeout_js -else = auto_session_expired_js diff --git a/spec/features/two_factor_authentication/sign_in_spec.rb b/spec/features/two_factor_authentication/sign_in_spec.rb index 1704b9c9d74..d4418a33822 100644 --- a/spec/features/two_factor_authentication/sign_in_spec.rb +++ b/spec/features/two_factor_authentication/sign_in_spec.rb @@ -105,25 +105,34 @@ expect(page).not_to have_css('.progress-steps') end - scenario 'user who enters OTP incorrectly 3 times is locked out for OTP validity period' do - user = create(:user, :signed_up) - sign_in_before_2fa(user) - click_button t('forms.buttons.submit.default') + context 'user enters OTP incorrectly 3 times', js: true do + it 'locks the user out and leaves user on the page during entire lockout period' do + allow(Figaro.env).to receive(:session_check_frequency).and_return('1') + allow(Figaro.env).to receive(:session_check_delay).and_return('2') - 3.times do - fill_in('code', with: 'bad-code') + user = create(:user, :signed_up) + sign_in_before_2fa(user) click_button t('forms.buttons.submit.default') - end - expect(page).to have_content t('titles.account_locked') + 3.times do + fill_in('code', with: 'bad-code') + click_button t('forms.buttons.submit.default') + end - # let 10 minutes (otp validity period) magically pass - user.update(second_factor_locked_at: Time.zone.now - (Devise.direct_otp_valid_for + 1.second)) + expect(page).to have_content t('titles.account_locked') + expect(page).to have_content('4 minutes and 54 seconds') + expect(page).to have_content('4 minutes and 53 seconds') - sign_in_before_2fa(user) - click_button t('forms.buttons.submit.default') + # let lockout period expire + user.update( + second_factor_locked_at: Time.zone.now - (Devise.direct_otp_valid_for + 1.second) + ) - expect(page).to have_content t('devise.two_factor_authentication.header_text') + sign_in_before_2fa(user) + click_button t('forms.buttons.submit.default') + + expect(page).to have_content t('devise.two_factor_authentication.header_text') + end end context 'user signs in while locked out' do diff --git a/spec/features/users/sign_in_spec.rb b/spec/features/users/sign_in_spec.rb index e9ce150addc..f4ca5b41f28 100644 --- a/spec/features/users/sign_in_spec.rb +++ b/spec/features/users/sign_in_spec.rb @@ -91,6 +91,21 @@ end end + context 'user only signs in via email and password', js: true do + it 'displays the session timeout warning' do + allow(Figaro.env).to receive(:session_check_frequency).and_return('1') + allow(Figaro.env).to receive(:session_check_delay).and_return('2') + allow(Figaro.env).to receive(:session_timeout_warning_seconds). + and_return(Devise.timeout_in.to_s) + + user = create(:user, :signed_up) + sign_in_user(user) + visit user_two_factor_authentication_path + + expect(page).to have_css('#session-timeout-msg') + end + end + context 'signed out' do it 'links to current page after session expires', js: true do allow(Devise).to receive(:timeout_in).and_return(0)