Fix 2FA/sign-in token sessions being valid after password change (#14802)

If someone tries logging in to an account and is prompted for a 2FA
code or sign-in token, even if the account's password or e-mail is
updated in the meantime, the session will show the prompt and allow
the login process to complete with a valid 2FA code or sign-in token
This commit is contained in:
Eugen Rochko 2020-11-12 23:05:01 +01:00 committed by GitHub
parent 9870b175b4
commit 8532429af7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 78 additions and 40 deletions

View file

@ -37,9 +37,11 @@ module TwoFactorAuthenticationConcern
def authenticate_with_two_factor
user = self.resource = find_user
if user.webauthn_enabled? && user_params[:credential].present? && session[:attempt_user_id]
if user.present? && session[:attempt_user_id].present? && session[:attempt_user_updated_at] != user.updated_at.to_s
restart_session
elsif user.webauthn_enabled? && user_params.key?(:credential) && session[:attempt_user_id]
authenticate_with_two_factor_via_webauthn(user)
elsif user_params[:otp_attempt].present? && session[:attempt_user_id]
elsif user_params.key?(:otp_attempt) && session[:attempt_user_id]
authenticate_with_two_factor_via_otp(user)
elsif user.present? && user.external_or_valid_password?(user_params[:password])
prompt_for_two_factor(user)
@ -50,7 +52,7 @@ module TwoFactorAuthenticationConcern
webauthn_credential = WebAuthn::Credential.from_get(user_params[:credential])
if valid_webauthn_credential?(user, webauthn_credential)
session.delete(:attempt_user_id)
clear_attempt_from_session
remember_me(user)
sign_in(user)
render json: { redirect_path: root_path }, status: :ok
@ -61,7 +63,7 @@ module TwoFactorAuthenticationConcern
def authenticate_with_two_factor_via_otp(user)
if valid_otp_attempt?(user)
session.delete(:attempt_user_id)
clear_attempt_from_session
remember_me(user)
sign_in(user)
else
@ -71,16 +73,18 @@ module TwoFactorAuthenticationConcern
end
def prompt_for_two_factor(user)
set_locale do
session[:attempt_user_id] = user.id
@body_classes = 'lighter'
@webauthn_enabled = user.webauthn_enabled?
@scheme_type = if user.webauthn_enabled? && user_params[:otp_attempt].blank?
'webauthn'
else
'totp'
end
render :two_factor
set_attempt_session(user)
@body_classes = 'lighter'
@webauthn_enabled = user.webauthn_enabled?
@scheme_type = begin
if user.webauthn_enabled? && user_params[:otp_attempt].blank?
'webauthn'
else
'totp'
end
end
set_locale { render :two_factor }
end
end