Class: Fernet::Token

Inherits:
Object
  • Object
show all
Includes:
Valcro
Defined in:
lib/fernet/token.rb

Overview

Internal: encapsulates a fernet token structure and validation

Defined Under Namespace

Classes: InvalidToken

Constant Summary collapse

DEFAULT_VERSION =

Internal: the default token version

0x80.freeze
MAX_CLOCK_SKEW =

Internal: max allowed clock skew for calculating TTL

60.freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(token, opts = {}) ⇒ Token

Internal: initializes a Token object

token - the string representation of this token opts - a has containing

  • secret - the secret, optionally base 64 encoded (required)

  • enforce_ttl - whether to enforce TTL upon validation. Defaults to

    value set in Configuration.enforce_ttl
    
  • ttl - number of seconds token is valid, defaults to

    Configuration.ttl
    


27
28
29
30
31
32
33
# File 'lib/fernet/token.rb', line 27

def initialize(token, opts = {})
  @token       = token
  @secret      = Secret.new(opts.fetch(:secret))
  @enforce_ttl = opts.fetch(:enforce_ttl) { Configuration.enforce_ttl }
  @ttl         = opts[:ttl] || Configuration.ttl
  @now         = opts[:now]
end

Class Method Details

.generate(opts) ⇒ Object

Internal: generates a Fernet Token

opts - a hash containing

  • secret - a string containing the secret, optionally base64 encoded

  • message - the message in plain text



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/fernet/token.rb', line 72

def self.generate(opts)
  unless opts[:secret]
    raise ArgumentError, 'Secret not provided'
  end
  secret = Secret.new(opts.fetch(:secret))
  encrypted_message, iv = Encryption.encrypt(
    key:     secret.encryption_key,
    message: opts[:message],
    iv:      opts[:iv]
  )
  issued_timestamp = (opts[:now] || Time.now).to_i

  version = opts[:version] || DEFAULT_VERSION
  payload = [version].pack("C") +
    BitPacking.pack_int64_bigendian(issued_timestamp) +
    iv +
    encrypted_message
  mac = OpenSSL::HMAC.digest('sha256', secret.signing_key, payload)
  new(Base64.urlsafe_encode64(payload + mac), secret: opts.fetch(:secret))
end

Instance Method Details

#messageObject

Internal: returns the decrypted message in this token

Raises InvalidToken if it cannot be decrypted or is invalid

Returns a string containing the original message in plain text



53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/fernet/token.rb', line 53

def message
  if valid?
    begin
      Encryption.decrypt(key: @secret.encryption_key,
                         ciphertext: encrypted_message,
                         iv: iv)
    rescue OpenSSL::Cipher::CipherError
      raise InvalidToken, "bad decrypt"
    end
  else
    raise InvalidToken, error_messages
  end
end

#to_sObject

Internal: returns the token as a string



36
37
38
# File 'lib/fernet/token.rb', line 36

def to_s
  @token
end

#valid?Boolean

Internal: Validates this token and returns true if it’s valid

Returns a boolean set to true if it’s valid, false otherwise

Returns:

  • (Boolean)


43
44
45
46
# File 'lib/fernet/token.rb', line 43

def valid?
  validate
  super
end