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 codes:
invalid_discovery_urldiscovery_metadata_fetch_faileddiscovery_metadata_invaliddiscovery_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.
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/verikloak/discovery.rb', line 49 def initialize(discovery_url:, connection: Verikloak::HTTP.default_connection, cache_ttl: 3600, allow_http: false) normalized_url = SafeUrl.normalize(discovery_url) unless normalized_url raise DiscoveryError.new('Invalid discovery URL: must be a non-empty HTTP(S) URL', code: 'invalid_discovery_url') end if SafeUrl.insecure_http?(normalized_url, allow_http: allow_http) 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.
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/verikloak/discovery.rb', line 79 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 |