12345678910111213141516171819202122232425262728293031323334353637383940414243 |
- # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
- class Auth::TwoFactor::AuthenticationMethod::AuthenticatorApp < Auth::TwoFactor::AuthenticationMethod
- ORDER = 2000
- def verify(payload, configuration = user_two_factor_preference_configuration)
- return verify_result(false) if payload.blank? || configuration.blank?
- secret = configuration[:secret]
- return verify_result(false) if secret.blank?
- last_otp_at = configuration[:last_otp_at]
- timestamp = totp(secret).verify(payload, drift_behind: 15, after: last_otp_at)
- # The provided code is invalid if we don't get a timestamp value.
- return verify_result(false) if timestamp.blank?
- # Return new configuration hash with the updated timestamp.
- verify_result(true, configuration: configuration, new_configuration: { last_otp_at: timestamp })
- end
- def initiate_configuration
- require 'rotp' # Only load when it is actually used
- secret = ROTP::Base32.random_base32
- {
- secret: secret,
- provisioning_uri: totp(secret).provisioning_uri(user.login),
- }
- end
- private
- def issuer
- Setting.get('organization').presence || Setting.get('product_name').presence || 'Zammad'
- end
- def totp(secret)
- require 'rotp' # Only load when it is actually used
- ROTP::TOTP.new(secret, issuer: issuer)
- end
- end
|