Class: Himari::Middlewares::MetadataClients

Inherits:
Object
  • Object
show all
Defined in:
lib/himari/middlewares/metadata_clients.rb

Overview

Enables OAuth Client ID Metadata Document support (draft-ietf-oauth-client-id-metadata-document). Its presence in the Rack env (RACK_KEY) advertises support in the discovery documents. It appends a single, long-lived OauthClientMetadata provider to the client chain (Middlewares::Client::RACK_KEY) so URL client_ids resolve through the same client_provider.find(id:) lookup the OIDC endpoints already use; the provider retains its HTTPX session and document cache across requests.

Must be placed after Middlewares::Config.

Options:

  • allowed_client_ids [Array<String, Regexp>] empty (default) accepts any compliant https URL; otherwise a client_id must match an entry (String exact, Regexp =~).

  • require_pkce [Boolean] force PKCE for metadata clients (default true; they are public).

  • ignore_localhost_redirect_uri_port [Boolean] relax the port of loopback redirect_uris when matching at the authorization endpoint (default true; see RFC 8252 ยง7.3).

  • skip_consent [Boolean] let metadata clients bypass the consent page (default false).

  • scopes [Array<String>] recognised scopes inherited by metadata clients; scopes outside this list are dropped from authorization requests (default openid, offline_access).

  • ssrf [true, false, Hash] SSRF filtering. true (default) restricts to https; a Hash is merged into the ssrf_filter plugin options (e.g. allowed_schemes); false disables it (only for an authorization server running on a loopback address).

  • user_agent [String] User-Agent header for fetches.

  • http_timeout [Hash] HTTPX timeout options.

  • max_response_size [Integer] reject documents larger than this many bytes (default 5 KiB).

  • cache_min_ttl / cache_max_ttl / cache_default_ttl [Integer] cache bounds in seconds.

  • cache_max_total_size [Integer] approximate cap on total cached document bytes; the oldest entries are evicted once exceeded (default 1 MiB).

Defined Under Namespace

Classes: Options

Constant Summary collapse

RACK_KEY =
'himari.metadata_clients'
DEFAULT_USER_AGENT =
"Himari-OauthClientMetadataFetch/#{Himari::VERSION} (+https://github.com/sorah/himari)"
DEFAULT_HTTP_TIMEOUT =

read_timeout is set explicitly: the stream plugin otherwise defaults it to Infinity, which would let a slow sender hold the fetch open indefinitely.

{connect_timeout: 5, request_timeout: 10, read_timeout: 10}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app, kwargs = {}) ⇒ MetadataClients

Returns a new instance of MetadataClients.



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/himari/middlewares/metadata_clients.rb', line 49

def initialize(app, kwargs = {})
  @app = app
  @options = Options.new(
    allowed_client_ids: kwargs.fetch(:allowed_client_ids, []),
    require_pkce: kwargs.fetch(:require_pkce, true),
    ignore_localhost_redirect_uri_port: kwargs.fetch(:ignore_localhost_redirect_uri_port, true),
    skip_consent: kwargs.fetch(:skip_consent, false),
    scopes: kwargs.fetch(:scopes, Himari::ClientRegistration::IMPLICIT_SCOPES),
    ssrf: kwargs.fetch(:ssrf, true),
    user_agent: kwargs.fetch(:user_agent, DEFAULT_USER_AGENT),
    http_timeout: kwargs.fetch(:http_timeout, DEFAULT_HTTP_TIMEOUT),
    max_response_size: kwargs.fetch(:max_response_size, 5120),
    cache_min_ttl: kwargs.fetch(:cache_min_ttl, 60),
    cache_max_ttl: kwargs.fetch(:cache_max_ttl, 86400),
    cache_default_ttl: kwargs.fetch(:cache_default_ttl, 300),
    cache_max_total_size: kwargs.fetch(:cache_max_total_size, 1_048_576),
  )
  @provider = Himari::ItemProviders::OauthClientMetadata.new(
    session: build_session(@options),
    allowed_client_ids: @options.allowed_client_ids,
    require_pkce: @options.require_pkce,
    ignore_localhost_redirect_uri_port: @options.ignore_localhost_redirect_uri_port,
    skip_consent: @options.skip_consent,
    scopes: @options.scopes,
    max_response_size: @options.max_response_size,
    cache_min_ttl: @options.cache_min_ttl,
    cache_max_ttl: @options.cache_max_ttl,
    cache_default_ttl: @options.cache_default_ttl,
    cache_max_total_size: @options.cache_max_total_size,
    logger: kwargs[:logger],
  )
end

Instance Attribute Details

#appObject (readonly)

Returns the value of attribute app.



82
83
84
# File 'lib/himari/middlewares/metadata_clients.rb', line 82

def app
  @app
end

#optionsObject (readonly)

Returns the value of attribute options.



82
83
84
# File 'lib/himari/middlewares/metadata_clients.rb', line 82

def options
  @options
end

Instance Method Details

#call(env) ⇒ Object



84
85
86
87
88
89
90
91
92
93
# File 'lib/himari/middlewares/metadata_clients.rb', line 84

def call(env)
  config = env[Himari::Middlewares::Config::RACK_KEY]
  raise "Himari::Middlewares::MetadataClients must be placed after Himari::Middlewares::Config" unless config

  env[RACK_KEY] = @options
  env[Himari::Middlewares::Client::RACK_KEY] ||= []
  env[Himari::Middlewares::Client::RACK_KEY] += [@provider]

  @app.call(env)
end