ruby 用于双因素身份验证(TOTP)的Rails mixin模块

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ruby 用于双因素身份验证(TOTP)的Rails mixin模块相关的知识,希望对你有一定的参考价值。

module OneTimePassword
  # Concern containing logic and methods for OTP authentication.
  # Is used Time-based One-time Password Algorithm(TOTP)
  # https://tools.ietf.org/html/rfc6238
  extend ActiveSupport::Concern

  OTP_DIGITS = 6
  OTP_NUMBER_OF_BACKUP_CODES = 10
  OTP_BACKUP_CODE_LENGTH = 12

  included do
    before_create do
      regenerate_otp_secret
    end
  end

  # Generation of a new OTP secret key
  # After changing the OTP secret key, the provisioning uri will also change
  def regenerate_otp_secret
    self.otp_secret_key = ROTP::Base32.random_base32
  end

  # Generation of a list backup codes
  # 1) Invalidates all existing backup codes
  # 2) Generates OTP_NUMBER_OF_BACKUP_CODES backup codes
  # 3) Stores the hashed backup codes in the otp_backup_codes
  # 4) Returns a plaintext array of the generated backup codes
  def regenerate_otp_backup_codes
    codes = Array.new(OTP_NUMBER_OF_BACKUP_CODES).map { SecureRandom.hex(OTP_BACKUP_CODE_LENGTH / 2) }
    hashed_codes = codes.map { |code| Devise::Encryptor.digest(self.class, code) }
    self.otp_backup_codes = hashed_codes

    codes
  end

  # Returns true and invalidates the given code
  # iff that code is a valid backup code.
  def invalidate_otp_backup_code(code)
    codes = self.otp_backup_codes || []

    codes.each do |backup_code|
      next unless Devise::Encryptor.compare(self.class, backup_code, code)

      codes.delete(backup_code)
      self.otp_backup_codes = codes
      self.save!
      return true
    end

    false
  end

  def otp_is_enabled?
    self.otp_is_enabled
  end

  # Authentication flow is enabled only if otp_is_enabled field is true
  def enable_otp
    codes = regenerate_otp_backup_codes
    self.otp_is_enabled = true
    self.save!
    codes
  end

  def disable_otp
    self.otp_is_enabled = false
    self.save
  end

  # Shows the current OTP code.
  # The code is similar to what will be displayed in the Google authenticator.
  # You can use it to authenticate via SMS and for testing.
  # @param time [Time] Time for code verification. By default is the current time.
  #   Explicit changing the test time is convenient for testing
  def otp_code(time = Time.current)
    ROTP::TOTP.new(self.otp_secret_key, digits: OTP_DIGITS).at(time, true)
  end

  # Method for verifying OTP code
  # @param code [String] OTP code.
  # @param drift [Integer] Allows to confirm the OTP code within 15 seconds after the expiration of its time.
  #   Drift allows you to level out the inaccuracy of time on different devices and server
  #   By default, the drift is set to 15 seconds.
  # @return [Boolean] OTP code verification result
  def authenticate_otp(code, drift = 15)
    totp = ROTP::TOTP.new(self.otp_secret_key, digits: OTP_DIGITS)
    totp.verify_with_drift(code, drift)
  end

  # Method for combining otp authorization and code recovery
  def authenticate_otp_or_invalidate_otp_backup_code(code)
    authenticate_otp(code) || invalidate_otp_backup_code(code)
  end

  # URI compatible with the Google Authenticator App to be scanned with the in-built QR Code scanner.
  # @param account [String] account name for which the Provisioning URI is generated. By default user email address
  # @param options [Hash] options for generate provisioning uri
  #   By default is blank hash.
  def provisioning_uri(account: nil, options: {})
    account ||= self.attributes["email"]
    options[:issuer] ||= otp_issuer
    ROTP::TOTP.new(self.otp_secret_key, options).provisioning_uri(account)
  end

  # Exclude the OTP secret key from all serializers
  def serializable_hash(options = nil)
    options ||= {}
    options[:except] = Array(options[:except])
    options[:except] << "otp_secret_key"
    super(options)
  end

  def otp_issuer
    raise "You must override `otp_issuer` method in #{self.class.name} model"
  end
end

以上是关于ruby 用于双因素身份验证(TOTP)的Rails mixin模块的主要内容,如果未能解决你的问题,请参考以下文章

对 ASP.NET MVC 使用 TOTP Microsoft 身份验证器

使用 Spring Boot 2 和 Spring Security 5 进行多因素身份验证

具有 JDBC 身份验证和 TOTP 的 CAS Server 3.51

双因素身份认证

PyPI提供双因素身份验证(2FA),已提高下载安全性

如何为wordpress网站添加双因素身份验证