gitlab-org--gitlab-foss/app/controllers/concerns/authenticates_with_two_fact...

108 lines
3.2 KiB
Ruby

# frozen_string_literal: true
module AuthenticatesWithTwoFactorForAdminMode
extend ActiveSupport::Concern
included do
include AuthenticatesWithTwoFactor
end
def admin_mode_prompt_for_two_factor(user)
return handle_locked_user(user) unless user.can?(:log_in)
session[:otp_user_id] = user.id
push_frontend_feature_flag(:webauthn)
if user.two_factor_webauthn_enabled?
setup_webauthn_authentication(user)
else
setup_u2f_authentication(user)
end
render 'admin/sessions/two_factor', layout: 'application'
end
def admin_mode_authenticate_with_two_factor
user = current_user
return handle_locked_user(user) unless user.can?(:log_in)
if user_params[:otp_attempt].present? && session[:otp_user_id]
admin_mode_authenticate_with_two_factor_via_otp(user)
elsif user_params[:device_response].present? && session[:otp_user_id]
if user.two_factor_webauthn_enabled?
admin_mode_authenticate_with_two_factor_via_webauthn(user)
else
admin_mode_authenticate_with_two_factor_via_u2f(user)
end
elsif user && user.valid_password?(user_params[:password])
admin_mode_prompt_for_two_factor(user)
else
invalid_login_redirect
end
end
def admin_mode_authenticate_with_two_factor_via_otp(user)
if valid_otp_attempt?(user)
# Remove any lingering user data from login
session.delete(:otp_user_id)
user.save! unless Gitlab::Database.read_only?
# The admin user has successfully passed 2fa, enable admin mode ignoring password
enable_admin_mode
else
admin_handle_two_factor_failure(user, 'OTP', _('Invalid two-factor code.'))
end
end
def admin_mode_authenticate_with_two_factor_via_u2f(user)
if U2fRegistration.authenticate(user, u2f_app_id, user_params[:device_response], session[:challenge])
admin_handle_two_factor_success
else
admin_handle_two_factor_failure(user, 'U2F', _('Authentication via U2F device failed.'))
end
end
def admin_mode_authenticate_with_two_factor_via_webauthn(user)
if Webauthn::AuthenticateService.new(user, user_params[:device_response], session[:challenge]).execute
admin_handle_two_factor_success
else
admin_handle_two_factor_failure(user, 'WebAuthn', _('Authentication via WebAuthn device failed.'))
end
end
private
def enable_admin_mode
if current_user_mode.enable_admin_mode!(skip_password_validation: true)
redirect_to redirect_path, notice: _('Admin mode enabled')
else
invalid_login_redirect
end
end
def invalid_login_redirect
flash.now[:alert] = _('Invalid login or password')
render :new
end
def admin_handle_two_factor_success
# Remove any lingering user data from login
session.delete(:otp_user_id)
session.delete(:challenge)
# The admin user has successfully passed 2fa, enable admin mode ignoring password
enable_admin_mode
end
def admin_handle_two_factor_failure(user, method, message)
user.increment_failed_attempts!
log_failed_two_factor(user, method)
Gitlab::AppLogger.info("Failed Admin Mode Login: user=#{user.username} ip=#{request.remote_ip} method=#{method}")
flash.now[:alert] = message
admin_mode_prompt_for_two_factor(user)
end
end