Skip to content

Implement .well-known/oauth-authorization-server for OAuth2#29015

Open
wendigo wants to merge 1 commit intomasterfrom
user/serafin/oauth2-well-known
Open

Implement .well-known/oauth-authorization-server for OAuth2#29015
wendigo wants to merge 1 commit intomasterfrom
user/serafin/oauth2-well-known

Conversation

@wendigo
Copy link
Copy Markdown
Contributor

@wendigo wendigo commented Apr 7, 2026

Tested with our singlenode-oauth2 endpoint which returns for this new endpoint:

{
  "issuer": "https://hydra:4444/",
  "authorization_endpoint": "https://hydra:4444/oauth2/auth",
  "token_endpoint": "https://hydra:4444/oauth2/token",
  "jwks_uri": "https://hydra:4444/.well-known/jwks.json",
  "scopes_supported": [
    "openid"
  ],
  "response_types_supported": "code"
}

Release notes

( ) This is not user-visible or is docs only, and no release notes are required.
( ) Release notes are required. Please propose a release note for me.
(x) Release notes are required, with the following suggested text:

## General
* Add `.well-known/oauth-authorization-server` endpoint to OAuth2 support ({issue}`issuenumber`)

@cla-bot cla-bot bot added the cla-signed label Apr 7, 2026
@wendigo wendigo requested review from dain and electrum April 7, 2026 15:49
Copy link
Copy Markdown
Member

@dain dain left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I asked a friend that knows OIDC really well and he thought this was a bad idea, so I asked ChatGPT to analyse this also, with a neutral prompt:

In trino we can be configured to accept OIDC tokens. IIRC they have to be signed by a specific issuer and need some specific field set.. this is all configurable. There is a PR #29015 to add a ".well-known/oauth-authorization-server" endpoint to the server, but I'm not sure if this is something we should have or not.

And it came back with a strong no:

I would lean no, at least not in the form in that PR.

The core issue is that /.well-known/oauth-authorization-server is the standard metadata document for an authorization server. It tells clients where that server’s authorization endpoint, token endpoint, JWKS, and related capabilities live. RFC 8414 is explicit that this metadata is for the authorization server itself, and that the issuer in the document must exactly match the issuer whose well-known URL was queried; otherwise the metadata “MUST NOT be used.”

But Trino, in this setup, is not the authorization server. Trino is an OAuth/OIDC client / relying party / protected resource that redirects users to the real IdP and validates tokens from that IdP. Trino’s own docs describe it that way: Trino uses the authorization code flow, redirects the browser to the authorization server, exchanges the code for a token, and can itself consume OIDC discovery metadata from the IdP.

That makes the current PR look semantically wrong. The implementation serves /.well-known/oauth-authorization-server from the Trino coordinator, but fills it with the upstream IdP’s metadata, including issuer = config.getIssuer() and the upstream authorization_endpoint, token_endpoint, and jwks_uri. So a client would fetch metadata from https://trino-coordinator/... and receive an issuer like https://hydra:4444/. Per RFC 8414, that is exactly the mismatch that clients are supposed to reject.

I went on to ask about what we should be doing and it said:

The right standard is OAuth 2.0 Protected Resource Metadata, published as RFC 9728 in 2025. It is specifically for a resource server / protected resource to publish metadata about itself, including which authorization server(s) clients should use.

The default well-known endpoint is:

/.well-known/oauth-protected-resource

So for a Trino server, the standard shape would be more like:

https://trino.example.com/.well-known/oauth-protected-resource

and the metadata can include:

  • resource: the resource identifier for the Trino server
  • authorization_servers: one or more issuer URLs for the authorization servers clients should use

There is also a standard way to point clients at that metadata dynamically: a WWW-Authenticate challenge can include a resource_metadata parameter, telling the client where to fetch the protected-resource metadata. RFC 9728 gives exactly that flow: client hits the resource, gets WWW-Authenticate: Bearer resource_metadata="...", fetches the resource metadata, then uses the listed issuer to fetch the authorization server metadata via RFC 8414.

So the standards split is now:

  • /.well-known/oauth-authorization-server = metadata for the token issuer / authorization server
  • /.well-known/oauth-protected-resource = metadata for the resource server that tells clients what issuer(s) to use

For Trino, that means:

  • if Trino is only accepting and validating tokens from some external IdP, then the standards-correct endpoint is oauth-protected-resource, not oauth-authorization-server
  • if Trino itself were actually issuing tokens, then oauth-authorization-server would make sense

One practical caveat: RFC 9728 is new, so many OAuth/OIDC clients probably do not support it yet. The spec itself says how a client learns the resource location is out of scope and may still be manual or application-specific.

metadata.put("response_types_supported", "code");
serverConfig.userinfoUrl().ifPresent(uri -> metadata.put("userinfo_endpoint", uri.toString()));
serverConfig.endSessionUrl().ifPresent(uri -> metadata.put("end_session_endpoint", uri.toString()));
serverConfig.accessTokenIssuer().ifPresent(issuer -> metadata.put("access_token_issuer", issuer));
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't a standard field by RFC 8414 sec. 3.2. The spec doesn't forbid this, but it isn't standard.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

2 participants