Skip to content

Discovery

Chenglei Yuan edited this page Jun 4, 2026 · 1 revision

Discovery

When discovery.enabled is true (the default), the proxy auto-discovers the OAuth2 token and authorization endpoints from the upstream URL, so you usually only need to supply UPSTREAM_URL and OAUTH2_CLIENT_ID.

How it works

Discovery runs in two stages, layering two RFCs:

1. Protected-resource metadata (RFC 9728)

The proxy fetches the upstream's /.well-known/oauth-protected-resource document. Its authorization_servers[0] entry points at the authorization server that protects the resource.

2. Authorization-server metadata (RFC 8414 / OpenID Connect)

Given the authorization server, the proxy fetches its metadata to learn the token_endpoint and authorization_endpoint. It tries multiple well-known candidates because servers differ in where they host metadata:

  • /.well-known/oauth-authorization-server (RFC 8414)
  • /.well-known/openid-configuration (OpenID Connect Discovery)

Both are tried with path permutations (the well-known segment placed at the root and after any path component of the issuer URL), and the first usable document wins.

Precedence

Discovery fills in gaps; it does not override values you set explicitly:

  • An explicit oauth2.tokenUrl / oauth2.authorizationUrl always wins.
  • Discovered endpoints are only used where you left a field unset.

Insecure endpoints are dropped

Discovered endpoints are passed through a secure-keeping filter (keepSecure): any discovered URL that is cleartext http:// to a non-loopback host is dropped with a warning rather than used. This prevents a compromised or misconfigured metadata document from silently downgrading you to an unauthenticated transport. (Explicitly configured insecure URLs are governed by allowInsecureHttp instead — see Security.)

Timeouts and failures

  • Each discovery HTTP request uses a short 5-second timeout.
  • DiscoveryResult fields are all optional; if discovery can't find something, the proxy falls back to whatever you configured explicitly.
  • If discovery yields nothing and no tokenUrl is configured, grant construction fails fast with a clear error (a token endpoint is mandatory).

Disabling discovery

Set either of:

{ "discovery": { "enabled": false } }
DISCOVERY_ENABLED=false

When disabled, you must provide oauth2.tokenUrl (and, for the interactive authorization_code flow, oauth2.authorizationUrl) yourself. See Configuration.

For the candidate-generation and metadata-parsing internals, see OAuth2 Internals.

Clone this wiki locally