ConduitMcp.OAuth.KeyProvider.JWKS (ConduitMCP v0.10.1)

Copy Markdown View Source

JWKS key provider that fetches keys from an HTTP endpoint with ETS caching.

Fetches JSON Web Key Sets from the authorization server's JWKS URI, caches them in ETS, and auto-refreshes on cache miss or expiration.

Configuration

auth: [
  strategy: :oauth,
  key_provider: {ConduitMcp.OAuth.KeyProvider.JWKS,
    jwks_uri: "https://auth.example.com/.well-known/jwks.json",
    cache_ttl: :timer.hours(1)}    # default: 1 hour
]

The jwks_uri must use https. For local development against a plain-HTTP authorization server, set allow_insecure_jwks: true in the provider config.

Fetches use conservative HTTP settings: redirects are not followed, requests time out (5s connect / 10s receive), and responses are capped at 1MB. If a refresh fails and previously fetched keys are still cached, those stale keys are served (with a logged warning) so a transient authorization-server outage does not hard-fail all authentication — bounded by :stale_max_age (default 24 hours), after which the provider fails closed so revoked keys cannot validate tokens indefinitely.

Security considerations

The jwks_uri must be trusted operator config — never client-derived. Fetches are hardened against SSRF abuse (https-only unless allow_insecure_jwks, redirects disabled, 1MB body cap), but the URI itself is not range-checked: a jwks_uri pointing at a private or link-local address — e.g. the cloud metadata endpoint http(s)://169.254.169.254/...is fetched, not rejected. Set jwks_uri from a configuration source you control. If it must come from a less-trusted source, restrict outbound egress at the network layer (the library deliberately does not block private ranges, since for most deployments the JWKS endpoint is an internal/private host).

Revocation lag during an outage. While the JWKS endpoint is unreachable, cached keys keep validating tokens until :stale_max_age (default 24h), then the provider fails closed. The trade-off: a key revoked during an outage can still validate tokens for up to :stale_max_age. Lower it if your threat model needs faster revocation; raise it to tolerate longer authorization-server outages.

Requirements

Requires the req package. Use 0.6.1 or newer: earlier versions carry advisories this provider can reach, including unbounded decompression driven by the response's content-type (GHSA — Req < 0.6.1). The 1MB cap below is applied to the decoded body, so it does not protect against a compression bomb on its own.

{:req, "~> 0.6"}