You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

47 lines
1.2 KiB

  1. # frozen_string_literal: true
  2. module TwoFactorAuthenticationConcern
  3. extend ActiveSupport::Concern
  4. included do
  5. prepend_before_action :authenticate_with_two_factor, if: :two_factor_enabled?, only: [:create]
  6. end
  7. def two_factor_enabled?
  8. find_user&.otp_required_for_login?
  9. end
  10. def valid_otp_attempt?(user)
  11. user.validate_and_consume_otp!(user_params[:otp_attempt]) ||
  12. user.invalidate_otp_backup_code!(user_params[:otp_attempt])
  13. rescue OpenSSL::Cipher::CipherError
  14. false
  15. end
  16. def authenticate_with_two_factor
  17. user = self.resource = find_user
  18. if user_params[:otp_attempt].present? && session[:attempt_user_id]
  19. authenticate_with_two_factor_attempt(user)
  20. elsif user.present? && user.external_or_valid_password?(user_params[:password])
  21. prompt_for_two_factor(user)
  22. end
  23. end
  24. def authenticate_with_two_factor_attempt(user)
  25. if valid_otp_attempt?(user)
  26. session.delete(:attempt_user_id)
  27. remember_me(user)
  28. sign_in(user)
  29. else
  30. flash.now[:alert] = I18n.t('users.invalid_otp_token')
  31. prompt_for_two_factor(user)
  32. end
  33. end
  34. def prompt_for_two_factor(user)
  35. session[:attempt_user_id] = user.id
  36. @body_classes = 'lighter'
  37. render :two_factor
  38. end
  39. end