Module: AuthenticatesWithTwoFactor
- Extended by:
- ActiveSupport::Concern
- Includes:
- Authn::WebauthnInstrumentation
- Included in:
- Profiles::AccountsController, Profiles::PasskeysController, Profiles::TwoFactorAuthsController, SessionsController
- Defined in:
- app/controllers/concerns/authenticates_with_two_factor.rb
Overview
AuthenticatesWithTwoFactor
Controller concern to handle two-factor authentication
Constant Summary
Constants included from Authn::WebauthnInstrumentation
Authn::WebauthnInstrumentation::PASSKEY_EVENT_TRACKING_ENTRY_POINT, Authn::WebauthnInstrumentation::PASSKEY_EVENT_TRACKING_STATUS
Instance Method Summary collapse
- #authenticate_with_two_factor ⇒ Object
- #handle_locked_user(user) ⇒ Object
- #handle_passwordless_flow ⇒ Object
- #locked_user_redirect(user) ⇒ Object
- #prompt_for_passwordless_authentication_via_passkey ⇒ Object
-
#prompt_for_two_factor(user) ⇒ Object
Store the user’s ID in the session for later retrieval and render the two factor code prompt.
Methods included from Authn::WebauthnInstrumentation
Methods included from Gitlab::InternalEventsTracking
Instance Method Details
#authenticate_with_two_factor ⇒ Object
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'app/controllers/concerns/authenticates_with_two_factor.rb', line 58 def authenticate_with_two_factor user = self.resource = find_user # If user does not complete two-factor authentication and authenticates as # another user within the same session, we should reset-two factor data # in the session, see # - https://gitlab.com/gitlab-org/gitlab-foss/-/issues/14900 # - https://gitlab.com/gitlab-org/gitlab/-/issues/20302 clear_two_factor_attempt! if session[:otp_user_id] != user.id return handle_locked_user(user) unless user.can?(:log_in) return handle_changed_user_password(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] authenticate_with_two_factor_via_webauthn(user) elsif user && user.valid_password?(user_params[:password]) prompt_for_two_factor(user) end rescue ActiveRecord::RecordInvalid => e # We expect User to always be valid. # Otherwise, raise internal server error instead of unprocessable entity to improve observability/alerting if e.record.is_a?(User) raise e. else raise e end end |
#handle_locked_user(user) ⇒ Object
40 41 42 43 44 |
# File 'app/controllers/concerns/authenticates_with_two_factor.rb', line 40 def handle_locked_user(user) clear_two_factor_attempt! locked_user_redirect(user) end |
#handle_passwordless_flow ⇒ Object
50 51 52 53 54 55 56 |
# File 'app/controllers/concerns/authenticates_with_two_factor.rb', line 50 def handle_passwordless_flow if passwordless_passkey_params[:device_response].present? authenticate_with_passwordless_authentication_via_passkey else prompt_for_passwordless_authentication_via_passkey end end |
#locked_user_redirect(user) ⇒ Object
46 47 48 |
# File 'app/controllers/concerns/authenticates_with_two_factor.rb', line 46 def locked_user_redirect(user) redirect_to new_user_session_path, alert: locked_user_redirect_alert(user) end |
#prompt_for_passwordless_authentication_via_passkey ⇒ Object
33 34 35 36 37 38 |
# File 'app/controllers/concerns/authenticates_with_two_factor.rb', line 33 def prompt_for_passwordless_authentication_via_passkey add_gon_variables setup_passkey_authentication render 'devise/sessions/passkeys' 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
19 20 21 22 23 24 25 26 27 28 29 30 31 |
# File 'app/controllers/concerns/authenticates_with_two_factor.rb', line 19 def prompt_for_two_factor(user) @user = user # rubocop:disable Gitlab/ModuleWithInstanceVariables -- Set @user for Devise views 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) add_gon_variables setup_webauthn_authentication(user) render 'devise/sessions/two_factor' end |