Class: ROTP::TOTP

Inherits:
OTP
  • Object
show all
Defined in:
lib/rotp/totp.rb

Constant Summary

Constants inherited from OTP

OTP::DEFAULT_DIGITS

Instance Attribute Summary collapse

Attributes inherited from OTP

#digest, #digits, #secret

Instance Method Summary collapse

Methods inherited from OTP

#generate_otp

Constructor Details

#initialize(s, options = {}) ⇒ TOTP

Returns a new instance of TOTP.

Parameters:

  • options (Hash) (defaults to: {})

    a customizable set of options

Options Hash (options):

  • interval (Integer) — default: 30

    the time interval in seconds for OTP This defaults to 30 which is standard.



8
9
10
11
12
# File 'lib/rotp/totp.rb', line 8

def initialize(s, options = {})
  @interval = options[:interval] || DEFAULT_INTERVAL
  @issuer = options[:issuer]
  super
end

Instance Attribute Details

#intervalObject (readonly)

Returns the value of attribute interval.



4
5
6
# File 'lib/rotp/totp.rb', line 4

def interval
  @interval
end

#issuerObject (readonly)

Returns the value of attribute issuer.



4
5
6
# File 'lib/rotp/totp.rb', line 4

def issuer
  @issuer
end

Instance Method Details

#at(time) ⇒ Object

Accepts either a Unix timestamp integer or a Time object. Time objects will be adjusted to UTC automatically

Parameters:

  • time (Time/Integer)

    the time to generate an OTP for, integer unix timestamp or Time object



17
18
19
# File 'lib/rotp/totp.rb', line 17

def at(time)
  generate_otp(timecode(time))
end

#nowInteger

Generate the current time OTP

Returns:

  • (Integer)

    the OTP as an integer



23
24
25
# File 'lib/rotp/totp.rb', line 23

def now
  generate_otp(timecode(Time.now))
end

#provisioning_uri(name) ⇒ String

Returns the provisioning URI for the OTP This can then be encoded in a QR Code and used to provision the Google Authenticator app

Parameters:

  • name (String)

    of the account

Returns:

  • (String)

    provisioning URI



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/rotp/totp.rb', line 56

def provisioning_uri(name)
  # The format of this URI is documented at:
  # https://github.com/google/google-authenticator/wiki/Key-Uri-Format
  # For compatibility the issuer appears both before that account name and also in the
  # query string.
  issuer_string = issuer.nil? ? '' : "#{Addressable::URI.escape(issuer)}:"
  params = {
    secret: secret,
    period: interval == 30 ? nil : interval,
    issuer: Addressable::URI.encode(issuer),
    digits: digits == DEFAULT_DIGITS ? nil : digits,
    algorithm: digest.casecmp('SHA1').zero? ? nil : digest.upcase
  }
  encode_params("otpauth://totp/#{issuer_string}#{Addressable::URI.escape(name)}", params)
end

#verify(otp, drift_ahead: 0, drift_behind: 0, after: nil, at: Time.now) ⇒ Integer?

Verifies the OTP passed in against the current time OTP and adjacent intervals up to drift. Excludes OTPs from ‘after` and earlier. Returns time value of matching OTP code for use in subsequent call.

Parameters:

  • otp (String)

    the one time password to verify

  • drift_behind (Integer) (defaults to: 0)

    how many seconds to look back

  • drift_ahead (Integer) (defaults to: 0)

    how many seconds to look ahead

  • after (Integer) (defaults to: nil)

    prevent token reuse, last login timestamp

  • at (Time) (defaults to: Time.now)

    time at which to generate and verify a particular otp. default Time.now

Returns:

  • (Integer, nil)

    the last successful timestamp interval



39
40
41
42
43
44
45
46
47
48
49
# File 'lib/rotp/totp.rb', line 39

def verify(otp, drift_ahead: 0, drift_behind: 0, after: nil, at: Time.now)
  timecodes = get_timecodes(at, drift_behind, drift_ahead)

  timecodes = timecodes.select { |t| t > timecode(after) } if after

  result = nil
  timecodes.each do |t|
    result = t * interval if super(otp, generate_otp(t))
  end
  result
end