Class: JWTKeeper::Token

Inherits:
Object
  • Object
show all
Defined in:
lib/jwt_keeper/token.rb

Overview

This class acts as the main interface to wrap the concerns of JWTs. Handling everything from encoding to invalidation.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ void

Initalizes a new web token

Parameters:

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

    the custom claims to encode

  • secret

    the secret to use during encoding, defaults to config

  • cookie_secret

    the cookie secret to use during encoding



12
13
14
15
16
17
18
19
20
21
22
23
24
# File 'lib/jwt_keeper/token.rb', line 12

def initialize(options = {})
  @secret = options.delete(:secret) || JWTKeeper.configuration.secret
  @cookie_secret = options.delete(:cookie_secret)
  @claims = {
    nbf: DateTime.now.to_i, # not before
    iat: DateTime.now.to_i, # issued at
    jti: SecureRandom.uuid  # JWT ID
  }

  @claims.merge!(JWTKeeper.configuration.base_claims)
  @claims.merge!(options)
  @claims[:exp] = @claims[:exp].to_i if @claims[:exp].is_a?(Time)
end

Instance Attribute Details

#claimsObject

Returns the value of attribute claims.



5
6
7
# File 'lib/jwt_keeper/token.rb', line 5

def claims
  @claims
end

Returns the value of attribute cookie_secret.



5
6
7
# File 'lib/jwt_keeper/token.rb', line 5

def cookie_secret
  @cookie_secret
end

#secretObject

Returns the value of attribute secret.



5
6
7
# File 'lib/jwt_keeper/token.rb', line 5

def secret
  @secret
end

Class Method Details

.create(options) ⇒ Token

Creates a new web token

Parameters:

  • options (Hash)

    the custom claims to encode

  • secret

    the secret to use during encoding, defaults to config

Returns:

  • (Token)

    token object



30
31
32
33
# File 'lib/jwt_keeper/token.rb', line 30

def self.create(options)
  cookie_secret = SecureRandom.hex(16) if JWTKeeper.configuration.cookie_lock
  new(options.merge(cookie_secret: cookie_secret))
end

.find(raw_token, secret: nil, cookie_secret: nil, iss: nil) ⇒ Token

Decodes and validates an existing token

Parameters:

  • raw_token (String)

    the raw token

  • cookie_secret (String) (defaults to: nil)

    the cookie secret

Returns:

  • (Token)

    token object



39
40
41
42
43
44
45
46
47
48
# File 'lib/jwt_keeper/token.rb', line 39

def self.find(raw_token, secret: nil, cookie_secret: nil, iss: nil)
  claims = decode(raw_token, secret: secret, cookie_secret: cookie_secret, iss: iss)
  return nil if claims.nil?

  new_token = new(secret: secret, cookie_secret: cookie_secret, iss: iss)
  new_token.claims = claims

  return nil if new_token.revoked?
  new_token
end

.revoke(token_jti) ⇒ void

This method returns an undefined value.

Revokes a web token

Parameters:

  • token_jti (String)

    the token unique id



62
63
64
# File 'lib/jwt_keeper/token.rb', line 62

def self.revoke(token_jti)
  Datastore.revoke(token_jti, JWTKeeper.configuration.expiry.from_now.to_i)
end

.rotate(token_jti) ⇒ void

This method returns an undefined value.

Sets a token to the pending rotation state. The expire is set to the maxium possible time but is inherently ignored by the token’s exp check and then rewritten with the revokation on rotate.

Parameters:

  • token_jti (String)

    the token unique id



55
56
57
# File 'lib/jwt_keeper/token.rb', line 55

def self.rotate(token_jti)
  Datastore.rotate(token_jti, JWTKeeper.configuration.expiry.from_now.to_i)
end

Instance Method Details

#idString

Easy interface for using the token’s id

Returns:

  • (String)

    token’s uuid



68
69
70
# File 'lib/jwt_keeper/token.rb', line 68

def id
  claims[:jti]
end

#invalid?Boolean

Checks if the token invalid?

Returns:

  • (Boolean)


120
121
122
123
124
125
126
# File 'lib/jwt_keeper/token.rb', line 120

def invalid?
  self.class.decode(
    encode,
    secret: secret,
    cookie_secret: cookie_secret
  ).nil? || revoked?
end

#pending?Boolean

Checks if a web token is pending a rotation

Returns:

  • (Boolean)


96
97
98
# File 'lib/jwt_keeper/token.rb', line 96

def pending?
  Datastore.pending?(id)
end

#revokevoid

This method returns an undefined value.

Revokes a web token



89
90
91
92
# File 'lib/jwt_keeper/token.rb', line 89

def revoke
  return if invalid?
  Datastore.revoke(id, claims[:exp] - DateTime.now.to_i)
end

#revoked?Boolean

Checks if a web token has been revoked

Returns:

  • (Boolean)


108
109
110
# File 'lib/jwt_keeper/token.rb', line 108

def revoked?
  Datastore.revoked?(id)
end

#rotate(new_claims = nil) ⇒ Token

Revokes and creates a new web token

Parameters:

  • new_claims (Hash) (defaults to: nil)

    Used to override and update claims during rotation

Returns:



75
76
77
78
79
80
81
82
83
84
85
# File 'lib/jwt_keeper/token.rb', line 75

def rotate(new_claims = nil)
  return self if claims[:iss] != JWTKeeper.configuration.issuer
  revoke

  new_claims ||= claims.except(:iss, :aud, :exp, :nbf, :iat, :jti)
  new_token = self.class.create(new_claims)

  @claims = new_token.claims
  @cookie_secret = new_token.cookie_secret
  self
end

Encodes the cookie

Returns:

  • (Hash)

    the cookie options



137
138
139
140
141
142
# File 'lib/jwt_keeper/token.rb', line 137

def to_cookie
  {
    value: cookie_secret,
    expires: Time.at(claims[:exp])
  }.merge(JWTKeeper.configuration.cookie_options)
end

#to_jwtString Also known as: to_s

Encodes the jwt

Returns:

  • (String)

    the encoded jwt



130
131
132
# File 'lib/jwt_keeper/token.rb', line 130

def to_jwt
  encode
end

#valid?Boolean

Checks if the token valid?

Returns:

  • (Boolean)


114
115
116
# File 'lib/jwt_keeper/token.rb', line 114

def valid?
  !invalid?
end

#version_mismatch?Boolean

Checks if a web token is pending a global rotation

Returns:

  • (Boolean)


102
103
104
# File 'lib/jwt_keeper/token.rb', line 102

def version_mismatch?
  claims[:ver] != JWTKeeper.configuration.version
end