Class: Authentic::Validator

Inherits:
Object
  • Object
show all
Defined in:
lib/authentic/validator.rb

Overview

Public: validates JWTs against JWKs.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Validator

Returns a new instance of Validator.

Raises:



12
13
14
15
16
17
18
# File 'lib/authentic/validator.rb', line 12

def initialize(options = {})
  @iss_whitelist = options.fetch(:iss_whitelist) { [] }
  raise IncompleteOptions if iss_whitelist.empty?

  max_age = options.fetch(:cache_max_age) { '10h' }
  @manager = options.fetch(:key_manager) { KeyManager.new(max_age) }
end

Instance Attribute Details

#iss_whitelistObject (readonly)

Returns the value of attribute iss_whitelist.



10
11
12
# File 'lib/authentic/validator.rb', line 10

def iss_whitelist
  @iss_whitelist
end

#managerObject (readonly)

Returns the value of attribute manager.



10
11
12
# File 'lib/authentic/validator.rb', line 10

def manager
  @manager
end

#optsObject (readonly)

Returns the value of attribute opts.



10
11
12
# File 'lib/authentic/validator.rb', line 10

def opts
  @opts
end

Instance Method Details

#decode_jwt(token) ⇒ Object

Decodes and does basic validation of JWT.

token - raw JWT.

Returns JSON::JWT



62
63
64
65
66
67
68
69
70
# File 'lib/authentic/validator.rb', line 62

def decode_jwt(token)
  raise InvalidToken, 'JWT was nil' unless token

  JSON::JWT.decode(token, :skip_verification).tap do |jwt|
    raise InvalidIssuer, 'JWT iss was not located in provided whitelist' unless iss_whitelist.include?(jwt[:iss])
  end
rescue JSON::JWT::InvalidFormat
  raise InvalidToken, 'JWT was in an invalid format'
end

#ensure_valid(token) ⇒ Object

Public: validates JWT, raises an error for invalid JWTs, errors requesting JWKs, the lack of valid JWKs, or non white listed ISS.

token - raw JWT.

Returns nothing.



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/authentic/validator.rb', line 38

def ensure_valid(token)
  decode_jwt(token).tap do |jwt|
    key = manager.get(jwt)

    # Slightly more accurate to raise a key error here for nil key,
    # rather then verify raising an error that would lead to InvalidToken
    raise InvalidKey if key.nil?

    exp = Time.at(jwt[:exp])
    raise ExpiredToken, "Token expired at #{exp}" unless exp > Time.now

    jwt.verify!(key)
  end
rescue JSON::JWT::UnexpectedAlgorithm, JSON::JWT::VerificationFailed
  raise InvalidToken, 'Failed to validate token against JWK'
rescue OpenSSL::PKey::PKeyError
  raise InvalidKey
end

#valid?(token) ⇒ Boolean

Public: validates JWT, returns true if valid, false if not.

token - raw JWT.

Returns boolean.

Returns:

  • (Boolean)


25
26
27
28
29
30
# File 'lib/authentic/validator.rb', line 25

def valid?(token)
  ensure_valid(token)
  true
rescue InvalidToken, ExpiredToken, InvalidKey, RequestError, InvalidIssuer
  false
end