Module: AuthenticatesWithTwoFactor

Extended by:
ActiveSupport::Concern
Included in:
OmniauthCallbacksController, SessionsController
Defined in:
app/controllers/concerns/authenticates_with_two_factor.rb

Overview

AuthenticatesWithTwoFactor

Controller concern to handle two-factor authentication

Instance Method Summary collapse

Instance Method Details

#authenticate_with_two_factorObject


47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'app/controllers/concerns/authenticates_with_two_factor.rb', line 47

def authenticate_with_two_factor
  user = self.resource = find_user
  return handle_locked_user(user) unless user.can?(:log_in)
  return handle_changed_user(user) if user_password_changed?(user)

  if user_params[:otp_attempt].present? && session[:otp_user_id]
    authenticate_with_two_factor_via_otp(user)
  elsif user_params[:device_response].present? && session[:otp_user_id]
    if user.two_factor_webauthn_enabled?
      authenticate_with_two_factor_via_webauthn(user)
    else
      authenticate_with_two_factor_via_u2f(user)
    end
  elsif user && user.valid_password?(user_params[:password])
    prompt_for_two_factor(user)
  end
end

#handle_locked_user(user) ⇒ Object


37
38
39
40
41
# File 'app/controllers/concerns/authenticates_with_two_factor.rb', line 37

def handle_locked_user(user)
  clear_two_factor_attempt!

  locked_user_redirect(user)
end

#locked_user_redirect(user) ⇒ Object


43
44
45
# File 'app/controllers/concerns/authenticates_with_two_factor.rb', line 43

def locked_user_redirect(user)
  redirect_to new_user_session_path, alert: locked_user_redirect_alert(user)
end

#prompt_for_two_factor(user) ⇒ Object

Store the user's ID in the session for later retrieval and render the two factor code prompt

The user must have been authenticated with a valid login and password before calling this method!

user - User record

Returns nil


18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'app/controllers/concerns/authenticates_with_two_factor.rb', line 18

def prompt_for_two_factor(user)
  # Set @user for Devise views
  @user = user # rubocop:disable Gitlab/ModuleWithInstanceVariables

  return handle_locked_user(user) unless user.can?(:log_in)

  session[:otp_user_id] = user.id
  session[:user_password_hash] = Digest::SHA256.hexdigest(user.encrypted_password)
  push_frontend_feature_flag(:webauthn)

  if user.two_factor_webauthn_enabled?
    setup_webauthn_authentication(user)
  else
    setup_u2f_authentication(user)
  end

  render 'devise/sessions/two_factor'
end