authenticator_app.rb 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. class Auth::TwoFactor::AuthenticationMethod::AuthenticatorApp < Auth::TwoFactor::AuthenticationMethod
  3. ORDER = 2000
  4. def verify(payload, configuration = user_two_factor_preference_configuration)
  5. return verify_result(false) if payload.blank? || configuration.blank?
  6. secret = configuration[:secret]
  7. return verify_result(false) if secret.blank?
  8. last_otp_at = configuration[:last_otp_at]
  9. timestamp = totp(secret).verify(payload, drift_behind: 15, after: last_otp_at)
  10. # The provided code is invalid if we don't get a timestamp value.
  11. return verify_result(false) if timestamp.blank?
  12. # Return new configuration hash with the updated timestamp.
  13. verify_result(true, configuration: configuration, new_configuration: { last_otp_at: timestamp })
  14. end
  15. def initiate_configuration
  16. require 'rotp' # Only load when it is actually used
  17. secret = ROTP::Base32.random_base32
  18. {
  19. secret: secret,
  20. provisioning_uri: totp(secret).provisioning_uri(user.login),
  21. }
  22. end
  23. private
  24. def issuer
  25. Setting.get('organization').presence || Setting.get('product_name').presence || 'Zammad'
  26. end
  27. def totp(secret)
  28. require 'rotp' # Only load when it is actually used
  29. ROTP::TOTP.new(secret, issuer: issuer)
  30. end
  31. end