skip to content

Why does an OAuth2 client fetch an authorization server's RFC 8414 metadata document rather than hardcoding its endpoint URLs?

level: juniorimportance: should knowfreq 42%

answer

  1. one configured value, not three URLs
  2. the server publishes, the client reads
  3. a JSON document under a well-known path
  4. /.well-known/oauth-authorization-server by default
  5. the issuer identifier is the only input

basics

~20 s

RFC 8414 metadata lets a client start from one configured value, the issuer identifier, and read the authorization server's endpoints and capabilities from a published JSON document, so the server can change them without every client being reconfigured.

solid answer

~40 s

An authorization server publishes a JSON document about itself at a URL derived from its issuer identifier, using the well-known path segment `/.well-known/oauth-authorization-server`. The document carries `authorization_endpoint`, `token_endpoint`, `jwks_uri` and capability fields such as `response_types_supported`, `grant_types_supported`, `scopes_supported`, `token_endpoint_auth_methods_supported` and `code_challenge_methods_supported`. A client configured with only the issuer identifier fetches it over https and learns where to send a user and where to exchange what comes back, instead of carrying URLs somebody pasted from a partner's documentation. That matters because the two parties are usually different organisations: the server can relocate an endpoint or start advertising a new capability without contacting every integrator. RFC 6749 defined the endpoints as roles but no way to discover their addresses; RFC 8414 is what added the document.

code

json · 11 lines
json
{
  "issuer": "https://id.example.org/contest",
  "authorization_endpoint": "https://id.example.org/contest/authorize",
  "token_endpoint": "https://id.example.org/contest/token",
  "jwks_uri": "https://id.example.org/contest/jwks",
  "response_types_supported": ["code"],
  "grant_types_supported": ["authorization_code", "refresh_token"],
  "scopes_supported": ["log:read", "log:submit"],
  "token_endpoint_auth_methods_supported": ["client_secret_basic", "private_key_jwt"],
  "code_challenge_methods_supported": ["S256"]
}

go deeper

for a junior

Recall the shape: the authorization server publishes a JSON document about itself, the client is configured with just the issuer identifier, and the endpoints come out of the document.

for a middle

Explain which members are required and which have defaults, and why an absent capability field does not mean the capability is unsupported.

for a senior

Show the operational judgment: how long you cache the document, what you do when a refetch disagrees with the cached copy, and why configuration holds one issuer rather than a block of URLs.

for a principal

Frame it as a coupling decision between organisations — what a partner can change unilaterally once you consume their document, and what you still pin by hand.

## What the document is An **authorization-server metadata document** is a JSON object that an authorization server publishes about itself, defined by RFC 8414. A client that knows one thing — the server's **issuer identifier**, a URL such as `https://id.example.org/contest` — derives a URL from it, fetches the document over https, and reads out where to send a user to authorize, where to exchange what comes back, and what the server is capable of. The default well-known path segment is `/.well-known/oauth-authorization-server`, and the response is an `application/json` object whose members are registered metadata field names. The issuer identifier is the only input. RFC 8414 constrains it: it is a URL using the **https** scheme with **no query or fragment components**. It may carry a path component, which is how one deployment can host many separately identified authorization servers. ## Why a client fetches it instead of storing URLs RFC 6749 defines the **authorization endpoint** (a browser destination) and the **token endpoint** (a back-channel POST target) as roles, not as addresses. It never says how a client learns them, so before RFC 8414 an integration began with two or three URLs copied out of a partner's documentation into a configuration file. That works exactly once. - The two parties are typically **different organisations** with no shared change-management process, so a configuration file is a copy of somebody else's deployment that nobody re-reads. - **Capabilities change more often than addresses.** A server that begins accepting a new client-authentication method or a new code challenge method can say so in one document rather than in an email to every integrator. - A **multi-tenant** server gives each tenant its own issuer identifier and therefore its own document, so the client's configuration is one value per tenant instead of a block of URLs per tenant. - One value is far easier to review, rotate between environments and get right than five, and a mistake in it fails loudly at fetch time rather than quietly at the wrong endpoint. ## What the document carries | group | members | what a client does with it | |---|---|---| | identity | `issuer` | compares it against the identifier it started from | | endpoints | `authorization_endpoint`, `token_endpoint`, `jwks_uri`, `registration_endpoint`, `revocation_endpoint`, `introspection_endpoint` | uses these addresses instead of configured ones | | capabilities | `response_types_supported`, `grant_types_supported`, `response_modes_supported`, `scopes_supported`, `token_endpoint_auth_methods_supported`, `token_endpoint_auth_signing_alg_values_supported`, `code_challenge_methods_supported` | decides what it may ask for and how it will authenticate | | provenance and prose | `signed_metadata`, `service_documentation` | verification material, and a link written for humans | ## Two members are always there; the rest is conditional RFC 8414 marks only **`issuer`** and **`response_types_supported`** as unconditionally REQUIRED. `authorization_endpoint` is required unless the server supports no grant type that uses it, and `token_endpoint` is required unless only the implicit grant is supported. Several capability fields carry **defaults**, so an absent member is not the same as an unsupported feature: - `grant_types_supported` absent means `authorization_code` and `implicit`; - `response_modes_supported` absent means `query` and `fragment`; - `token_endpoint_auth_methods_supported` absent means `client_secret_basic`. A client that reads every absent member as "unsupported" will refuse to talk to a conforming server; a client that assumes every member is present will dereference one that is missing. Both are common, and both are avoided by reading the field's own default. ## How it is used in practice 1. The client is configured with one value: the issuer identifier. 2. It derives the metadata URL from that identifier. 3. It fetches the document over https and confirms that the `issuer` member is identical to the identifier it started from. 4. It reads the endpoints and capability fields, caches the document for a sensible period, and refetches rather than freezing the values into configuration. ## What the document is not - It is **not** a per-client entitlement list. `scopes_supported` advertises what the server understands, not what this particular client has been granted. - It is **not** the client's own metadata. A client's `redirect_uris` and `grant_types` are its record at the server, submitted when the client was registered; they are not members of this document. - It is **not** an authenticated exchange. The document is public and unauthenticated, and every reader of that issuer's document gets the same bytes, which is exactly why the comparison of the returned `issuer` against the configured identifier is the check that carries the weight. - It is **not** a substitute for knowing the issuer. Everything the client goes on to trust descends from the one value it was configured with.

  • What does RFC 8414 require of the issuer identifier itself?
    It is a URL using the `https` scheme with no query or fragment components. It may carry a path component — that is how one host serves several separately identified authorization servers, and it is also what makes the metadata URL construction rule worth knowing.
  • The document is public and unauthenticated — so what stops a client acting on the wrong one?
    Three things, in order: the retrieval runs over https with the server's certificate validated; the `issuer` member returned must be identical to the identifier the client used to build the URL, and RFC 8414 says the data must not be used otherwise; and where the document travels a path the client does not fully trust, `signed_metadata` carries the same claims in a signed JWT.
  • Does `scopes_supported` tell a client which scopes it may request?
    No. It is a RECOMMENDED advertisement of the scope values this authorization server understands. What a given client is actually allowed to ask for is a property of that client's registration and of what the resource owner approves, not of the metadata document.

saying these in an interview costs you the question

  • Thinks the client publishes the metadata document for the server to read.
  • Believes every member listed in RFC 8414 is required to be present.
  • Assumes the document may be served over plain http.
  • Confuses it with the client metadata submitted when a client is registered.
  • Treats fetching it as an authentication step rather than a public lookup.