Class: Verikloak::Discovery
- Inherits:
-
Object
- Object
- Verikloak::Discovery
- Defined in:
- lib/verikloak/discovery.rb
Overview
Fetches and caches the OpenID Connect Discovery document.
This class retrieves the discovery metadata from an OpenID Connect provider (e.g., Keycloak) using the ‘.well-known/openid-configuration` endpoint. It validates required fields such as `jwks_uri` and `issuer`, and supports:
-
Dependency Injection of Faraday connection for testing and middleware
-
In-memory caching with configurable TTL
-
Thread safety via Mutex
-
Automatic handling of common HTTP statuses (including multi-hop redirects)
### Thread-safety ‘#fetch!` is synchronized, so concurrent callers share the same cached value and refresh.
### Errors Raises DiscoveryError with one of the following ‘code`s:
-
‘invalid_discovery_url`
-
‘discovery_metadata_fetch_failed`
-
‘discovery_metadata_invalid`
-
‘discovery_redirect_error`
Constant Summary collapse
- REQUIRED_FIELDS =
Required keys that must be present in the discovery document.
%w[jwks_uri issuer].freeze
Instance Method Summary collapse
-
#fetch! ⇒ Hash
Fetches and parses the discovery document, using the in-memory cache if fresh.
-
#initialize(discovery_url:, connection: Verikloak::HTTP.default_connection, cache_ttl: 3600, allow_http: false) ⇒ Discovery
constructor
A new instance of Discovery.
Constructor Details
#initialize(discovery_url:, connection: Verikloak::HTTP.default_connection, cache_ttl: 3600, allow_http: false) ⇒ Discovery
Returns a new instance of Discovery.
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/verikloak/discovery.rb', line 65 def initialize(discovery_url:, connection: Verikloak::HTTP.default_connection, cache_ttl: 3600, allow_http: false) normalized_url = discovery_url.is_a?(String) ? discovery_url.strip : discovery_url unless normalized_url.is_a?(String) && normalized_url.match?(%r{^https?://}) raise DiscoveryError.new('Invalid discovery URL: must be a non-empty HTTP(S) URL', code: 'invalid_discovery_url') end unless allow_http || normalized_url.start_with?('https://') raise DiscoveryError.new( 'Discovery URL must use HTTPS. Set allow_http: true to permit plain HTTP (development only).', code: 'insecure_discovery_url' ) end @discovery_url = normalized_url @conn = connection @cache_ttl = cache_ttl @allow_http = allow_http @cached_json = nil @fetched_at = nil @mutex = Mutex.new end |
Instance Method Details
#fetch! ⇒ Hash
Fetches and parses the discovery document, using the in-memory cache if fresh.
Cache freshness is determined by ‘cache_ttl` from initialization.
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/verikloak/discovery.rb', line 95 def fetch! @mutex.synchronize do # Return cached if within TTL return @cached_json if @cached_json && (Time.now - @fetched_at) < @cache_ttl # Fetch fresh document json = with_error_handling { fetch_and_parse_json_from_url } validate_required_fields!(json) # Update cache @cached_json = json @fetched_at = Time.now json end end |