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

.revoked?(token_jti) ⇒ Boolean

Checks if a web token has been revoked

Returns:

  • (Boolean)


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

def self.revoked?(token_jti)
  Datastore.revoked?(token_jti)
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



74
75
76
# File 'lib/jwt_keeper/token.rb', line 74

def id
  claims[:jti]
end

#invalid?Boolean

Checks if the token invalid?

Returns:

  • (Boolean)


126
127
128
129
130
131
132
# File 'lib/jwt_keeper/token.rb', line 126

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)


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

def pending?
  Datastore.pending?(id)
end

#revokevoid

This method returns an undefined value.

Revokes a web token



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

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)


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

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:



81
82
83
84
85
86
87
88
89
90
91
# File 'lib/jwt_keeper/token.rb', line 81

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



143
144
145
146
147
148
# File 'lib/jwt_keeper/token.rb', line 143

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



136
137
138
# File 'lib/jwt_keeper/token.rb', line 136

def to_jwt
  encode
end

#valid?Boolean

Checks if the token valid?

Returns:

  • (Boolean)


120
121
122
# File 'lib/jwt_keeper/token.rb', line 120

def valid?
  !invalid?
end

#version_mismatch?Boolean

Checks if a web token is pending a global rotation

Returns:

  • (Boolean)


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

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