authenticator_app.rb 1.3 KB

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