Commit a602df30 authored by Robert Speicher's avatar Robert Speicher

Pass the "Remember me" value to the 2FA token form

Prior, if a user had 2FA enabled and checked the "Remember me" field,
the setting was ignored because the OTP input was on a new form and the
value was never passed.

Closes #18000
parent de20bd5b
class SessionsController < Devise::SessionsController class SessionsController < Devise::SessionsController
include AuthenticatesWithTwoFactor include AuthenticatesWithTwoFactor
include Devise::Controllers::Rememberable
include Recaptcha::ClientHelper include Recaptcha::ClientHelper
skip_before_action :check_2fa_requirement, only: [:destroy] skip_before_action :check_2fa_requirement, only: [:destroy]
...@@ -96,6 +97,7 @@ class SessionsController < Devise::SessionsController ...@@ -96,6 +97,7 @@ class SessionsController < Devise::SessionsController
# Remove any lingering user data from login # Remove any lingering user data from login
session.delete(:otp_user_id) session.delete(:otp_user_id)
remember_me(user) if user_params[:remember_me] == '1'
sign_in(user) and return sign_in(user) and return
else else
flash.now[:alert] = 'Invalid two-factor code.' flash.now[:alert] = 'Invalid two-factor code.'
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
%h3 Two-factor Authentication %h3 Two-factor Authentication
.login-body .login-body
= form_for(resource, as: resource_name, url: session_path(resource_name), method: :post) do |f| = form_for(resource, as: resource_name, url: session_path(resource_name), method: :post) do |f|
= f.hidden_field :remember_me, value: params[resource_name][:remember_me]
= f.text_field :otp_attempt, class: 'form-control', placeholder: 'Two-factor Authentication code', required: true, autofocus: true = f.text_field :otp_attempt, class: 'form-control', placeholder: 'Two-factor Authentication code', required: true, autofocus: true
%p.help-block.hint Enter the code from the two-factor app on your mobile device. If you've lost your device, you may enter one of your recovery codes. %p.help-block.hint Enter the code from the two-factor app on your mobile device. If you've lost your device, you may enter one of your recovery codes.
.prepend-top-20 .prepend-top-20
......
...@@ -35,6 +35,27 @@ describe SessionsController do ...@@ -35,6 +35,27 @@ describe SessionsController do
post(:create, { user: user_params }, { otp_user_id: user.id }) post(:create, { user: user_params }, { otp_user_id: user.id })
end end
context 'remember_me field' do
it 'sets a remember_user_token cookie when enabled' do
allow(controller).to receive(:find_user).and_return(user)
expect(controller).
to receive(:remember_me).with(user).and_call_original
authenticate_2fa(remember_me: '1', otp_attempt: user.current_otp)
expect(response.cookies['remember_user_token']).to be_present
end
it 'does nothing when disabled' do
allow(controller).to receive(:find_user).and_return(user)
expect(controller).not_to receive(:remember_me)
authenticate_2fa(remember_me: '0', otp_attempt: user.current_otp)
expect(response.cookies['remember_user_token']).to be_nil
end
end
## ##
# See #14900 issue # See #14900 issue
# #
......
...@@ -32,7 +32,7 @@ feature 'Login', feature: true do ...@@ -32,7 +32,7 @@ feature 'Login', feature: true do
let(:user) { create(:user, :two_factor) } let(:user) { create(:user, :two_factor) }
before do before do
login_with(user) login_with(user, remember: true)
expect(page).to have_content('Two-factor Authentication') expect(page).to have_content('Two-factor Authentication')
end end
...@@ -52,6 +52,12 @@ feature 'Login', feature: true do ...@@ -52,6 +52,12 @@ feature 'Login', feature: true do
expect(current_path).to eq root_path expect(current_path).to eq root_path
end end
it 'persists remember_me value via hidden field' do
field = first('input#user_remember_me', visible: false)
expect(field.value).to eq '1'
end
it 'blocks login with invalid code' do it 'blocks login with invalid code' do
enter_code('foo') enter_code('foo')
expect(page).to have_content('Invalid two-factor code') expect(page).to have_content('Invalid two-factor code')
......
...@@ -27,10 +27,12 @@ module LoginHelpers ...@@ -27,10 +27,12 @@ module LoginHelpers
# Internal: Login as the specified user # Internal: Login as the specified user
# #
# user - User instance to login with # user - User instance to login with
def login_with(user) # remember - Whether or not to check "Remember me" (default: false)
def login_with(user, remember: false)
visit new_user_session_path visit new_user_session_path
fill_in "user_login", with: user.email fill_in "user_login", with: user.email
fill_in "user_password", with: "12345678" fill_in "user_password", with: "12345678"
check 'user_remember_me' if remember
click_button "Sign in" click_button "Sign in"
Thread.current[:current_user] = user Thread.current[:current_user] = user
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment