Class: Authentic::KeyManager
- Inherits:
-
Object
- Object
- Authentic::KeyManager
- Defined in:
- lib/authentic/key_manager.rb
Overview
Internal: manages JWK retrieval, caching, and validation.
Instance Attribute Summary collapse
-
#store ⇒ Object
readonly
Returns the value of attribute store.
-
#well_known ⇒ Object
readonly
Returns the value of attribute well_known.
Instance Method Summary collapse
-
#get(jwt) ⇒ Object
Public: retrieves JWK.
-
#hydrate_iss_keys(iss) ⇒ Object
Internal: hydrates JWK cache.
-
#hydrate_store(keys, iss) ⇒ Object
Internal: hydrates key store.
-
#initialize(max_age) ⇒ KeyManager
constructor
A new instance of KeyManager.
-
#json_req(uri) ⇒ Object
Internal: performs JSON request.
-
#valid_key(key) ⇒ Object
Internal: performs JSON request.
-
#valid_rsa_key(key) ⇒ Object
Internal: validates RSA key.
Constructor Details
#initialize(max_age) ⇒ KeyManager
Returns a new instance of KeyManager.
12 13 14 15 |
# File 'lib/authentic/key_manager.rb', line 12 def initialize(max_age) @store = KeyStore.new(max_age) @well_known = '/.well-known/openid-configuration' end |
Instance Attribute Details
#store ⇒ Object (readonly)
Returns the value of attribute store.
10 11 12 |
# File 'lib/authentic/key_manager.rb', line 10 def store @store end |
#well_known ⇒ Object (readonly)
Returns the value of attribute well_known.
10 11 12 |
# File 'lib/authentic/key_manager.rb', line 10 def well_known @well_known end |
Instance Method Details
#get(jwt) ⇒ Object
Public: retrieves JWK.
jwt - JSON::JWT.
Returns JSON::JWK.
22 23 24 25 26 27 28 29 30 31 32 |
# File 'lib/authentic/key_manager.rb', line 22 def get(jwt) iss = jwt.fetch(:iss) result = store.get(iss, jwt.kid) return result unless result.nil? # Refresh all keys for an issuer while I have the updated data on hand hydrate_iss_keys iss store.get(iss, jwt.kid) end |
#hydrate_iss_keys(iss) ⇒ Object
Internal: hydrates JWK cache.
iss - issuer URI.
Returns nothing.
73 74 75 76 77 78 79 80 81 82 |
# File 'lib/authentic/key_manager.rb', line 73 def hydrate_iss_keys(iss) uri = iss.sub(%r{[\/]+$}, '') + well_known json = json_req uri.to_s body = json_req json['jwks_uri'] raise InvalidKey, "no valid JWK found, #{json['jwks_uri']}" if body['keys']&.blank? keys = body['keys'].select { |key| valid_key(key) } hydrate_store(keys, iss) end |
#hydrate_store(keys, iss) ⇒ Object
Internal: hydrates key store.
keys - array of keys hash. iss - JWT issuer endpoint.
Returns nothing.
90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/authentic/key_manager.rb', line 90 def hydrate_store(keys, iss) keys.each do |key| store.set( iss, key['kid'], JSON::JWK.new( kty: key['kty'], e: key['e'], n: key['n'], kid: key['kid'] ) ) end end |
#json_req(uri) ⇒ Object
Internal: performs JSON request.
uri - endpoint to request.
Returns JSON.
57 58 59 60 61 62 63 64 65 66 |
# File 'lib/authentic/key_manager.rb', line 57 def json_req(uri) begin resp = RestClient.get(uri, accept: :json) rescue RestClient::ExceptionWithResponse => e code = e.response.code raise RequestError.new("failed to retrieve JWK, status #{code}", code) end JSON.parse resp.body end |
#valid_key(key) ⇒ Object
Internal: performs JSON request.
key - hash with JWK data.
Returns boolean.
48 49 50 |
# File 'lib/authentic/key_manager.rb', line 48 def valid_key(key) valid_rsa_key(key) && (key['x5c']&.length || (key['n'] && key['e'])) end |
#valid_rsa_key(key) ⇒ Object
Internal: validates RSA key.
key - hash with key data.
Returns boolean.
39 40 41 |
# File 'lib/authentic/key_manager.rb', line 39 def valid_rsa_key(key) key['use'] == 'sig' && key['kty'] == 'RSA' && key['kid'] end |