2023-02-21 13:56:49 -08:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2020-10-18 01:39:46 -07:00
|
|
|
class User::SessionsController < Devise::SessionsController
|
2020-10-23 11:45:06 -07:00
|
|
|
def new
|
|
|
|
session.delete(:user_sign_in_uid)
|
|
|
|
super
|
|
|
|
end
|
|
|
|
|
2020-10-18 01:39:46 -07:00
|
|
|
def create
|
2023-02-21 13:56:49 -08:00
|
|
|
authenticate!
|
2020-10-18 01:39:46 -07:00
|
|
|
|
2020-10-18 02:39:28 -07:00
|
|
|
if resource.active_for_authentication? && resource.otp_module_enabled?
|
2020-10-18 01:39:46 -07:00
|
|
|
if params[:user][:otp_attempt].blank?
|
2023-02-21 13:56:49 -08:00
|
|
|
prompt_for_2fa
|
2020-10-18 01:39:46 -07:00
|
|
|
else
|
2023-02-21 13:56:49 -08:00
|
|
|
attempt_2fa
|
2020-10-18 01:39:46 -07:00
|
|
|
end
|
|
|
|
else
|
|
|
|
continue_sign_in(resource, resource_name)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
2023-02-21 13:56:49 -08:00
|
|
|
def authenticate!
|
|
|
|
self.resource = session.key?(:user_sign_in_uid) ? User.find(session.delete(:user_sign_in_uid)) : warden.authenticate!(auth_options)
|
|
|
|
end
|
|
|
|
|
2020-10-18 01:39:46 -07:00
|
|
|
def continue_sign_in(resource, resource_name)
|
|
|
|
set_flash_message!(:notice, :signed_in)
|
|
|
|
sign_in(resource_name, resource)
|
|
|
|
yield resource if block_given?
|
|
|
|
respond_with resource, location: after_sign_in_path_for(resource)
|
|
|
|
end
|
2023-02-21 13:56:49 -08:00
|
|
|
|
|
|
|
def prompt_for_2fa
|
|
|
|
session[:user_sign_in_uid] = resource.id
|
|
|
|
sign_out(resource)
|
|
|
|
warden.lock!
|
2023-03-23 10:26:58 -07:00
|
|
|
render "auth/two_factor_authentication"
|
2023-02-21 13:56:49 -08:00
|
|
|
end
|
|
|
|
|
|
|
|
def attempt_2fa
|
|
|
|
if params[:user][:otp_attempt].length == 8
|
|
|
|
try_recovery_code
|
|
|
|
elsif resource.authenticate_otp(params[:user][:otp_attempt], drift: APP_CONFIG.fetch(:otp_drift_period, 30).to_i)
|
|
|
|
continue_sign_in(resource, resource_name)
|
|
|
|
else
|
|
|
|
fail_2fa
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def try_recovery_code
|
|
|
|
found = TotpRecoveryCode.where(user_id: resource.id, code: params[:user][:otp_attempt].downcase).delete_all
|
|
|
|
if found == 1
|
|
|
|
flash[:info] = t(".info", count: TotpRecoveryCode.where(user_id: resource.id).count)
|
|
|
|
continue_sign_in(resource, resource_name)
|
|
|
|
else
|
|
|
|
fail_2fa
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def fail_2fa
|
|
|
|
sign_out(resource)
|
|
|
|
flash[:error] = t(".error")
|
|
|
|
redirect_to new_user_session_url
|
|
|
|
end
|
|
|
|
end
|