recovery_codes.rb 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. class Auth::TwoFactor::RecoveryCodes < Auth::TwoFactor::Method
  3. NUMBER_OF_CODES = 10
  4. CODE_LENGTH = 16
  5. def verify(code)
  6. return verify_result(false) if !exists? || code.blank?
  7. configuration = user_two_factor_preference_configuration
  8. hashed_code = configuration[:codes].detect { |saved_code| PasswordHash.verified?(saved_code, code) }
  9. return verify_result(false) if hashed_code.blank?
  10. configuration[:codes].delete(hashed_code)
  11. verify_result(true, new_configuration: configuration)
  12. end
  13. def generate
  14. codes = []
  15. NUMBER_OF_CODES.times do
  16. # The hex string has length 2*n.
  17. codes << SecureRandom.hex(CODE_LENGTH / 2)
  18. end
  19. hashed_codes = codes.map { |code| PasswordHash.crypt(code) }
  20. if exists?
  21. update_user_config({ codes: hashed_codes })
  22. else
  23. create_user_config({ codes: hashed_codes })
  24. end
  25. codes
  26. end
  27. def related_setting_name
  28. 'two_factor_authentication_recovery_codes'
  29. end
  30. def exists?
  31. user_two_factor_preference.present?
  32. end
  33. def user_two_factor_preference
  34. user&.two_factor_preferences&.recovery_codes
  35. end
  36. end