Class: RackJwtVerifier::KeySource::Remote
- Inherits:
-
Object
- Object
- RackJwtVerifier::KeySource::Remote
- Defined in:
- lib/rack_jwt_verifier/key_source.rb
Overview
Shared machinery for key material fetched over HTTPS: caching, strict timeouts, a size cap, single-flight fetching within the process, and a rate-limited refresh for key rotation. Subclasses say how to parse the body and which cache namespace to use.
Direct Known Subclasses
Constant Summary collapse
- DEFAULT_HTTP_TIMEOUT =
Timeout (seconds) applied separately to opening the connection and to reading the response. Kept short so a slow endpoint cannot pin every request thread on a cache miss.
5- MAX_RESPONSE_BYTES =
Largest response body (bytes) we are willing to read. A PEM key is well under 1 KB and a JWKS with a handful of keys a few KB.
64 * 1024
- DEFAULT_CACHE_TTL =
How long (seconds) fetched material is served from the cache.
300- DEFAULT_REFETCH_INTERVAL =
Minimum gap (seconds) between two rotation-triggered refetches, so a flood of tokens with bad signatures or unknown kids cannot turn into a flood of requests to the provider.
60
Instance Attribute Summary collapse
-
#cache_key ⇒ Object
readonly
Returns the value of attribute cache_key.
-
#url ⇒ Object
readonly
Returns the value of attribute url.
Instance Method Summary collapse
-
#initialize(url:, cache:, cache_ttl: DEFAULT_CACHE_TTL, http_timeout: DEFAULT_HTTP_TIMEOUT, refetch_interval: DEFAULT_REFETCH_INTERVAL, allow_insecure_http: false, logger: nil) ⇒ Remote
constructor
A new instance of Remote.
-
#refresh! ⇒ Object
Refetches the material unless a refresh happened less than refetch_interval seconds ago.
Constructor Details
#initialize(url:, cache:, cache_ttl: DEFAULT_CACHE_TTL, http_timeout: DEFAULT_HTTP_TIMEOUT, refetch_interval: DEFAULT_REFETCH_INTERVAL, allow_insecure_http: false, logger: nil) ⇒ Remote
Returns a new instance of Remote.
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/rack_jwt_verifier/key_source.rb', line 118 def initialize(url:, cache:, cache_ttl: DEFAULT_CACHE_TTL, http_timeout: DEFAULT_HTTP_TIMEOUT, refetch_interval: DEFAULT_REFETCH_INTERVAL, allow_insecure_http: false, logger: nil) @url = url.to_s @uri = parse_url(@url, allow_insecure_http: allow_insecure_http) @cache = cache @logger = logger || Logger.new(IO::NULL) @cache_ttl = cache_ttl @http_timeout = http_timeout @refetch_interval = refetch_interval # Scoped to the URL so two verifiers sharing one cache store (two SSO # providers behind one Redis) never read each other's key. @cache_key = "#{cache_key_prefix}:#{Digest::SHA256.hexdigest(@url)[0, 16]}" @fetch_lock = Mutex.new # single-flight: one network fetch per process on a cold cache @state_lock = Mutex.new # guards @parsed and @last_refetch_at @parsed = nil # [body, parsed material] of the last body parsed @last_refetch_at = nil # monotonic clock end |
Instance Attribute Details
#cache_key ⇒ Object (readonly)
Returns the value of attribute cache_key.
116 117 118 |
# File 'lib/rack_jwt_verifier/key_source.rb', line 116 def cache_key @cache_key end |
#url ⇒ Object (readonly)
Returns the value of attribute url.
116 117 118 |
# File 'lib/rack_jwt_verifier/key_source.rb', line 116 def url @url end |
Instance Method Details
#refresh! ⇒ Object
Refetches the material unless a refresh happened less than refetch_interval seconds ago. Returns true if it actually refetched.
139 140 141 142 143 144 145 146 147 148 |
# File 'lib/rack_jwt_verifier/key_source.rb', line 139 def refresh! @state_lock.synchronize do now = monotonic_now return false if @last_refetch_at && now - @last_refetch_at < @refetch_interval @last_refetch_at = now end fetch_and_store true end |