Why does an OAuth2 client fetch an authorization server's RFC 8414 metadata document rather than hardcoding its endpoint URLs?
answer
- one configured value, not three URLs
- the server publishes, the client reads
- a JSON document under a well-known path
- /.well-known/oauth-authorization-server by default
- the issuer identifier is the only input
basics
~20 sRFC 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 sAn 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{
"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
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.
Explain which members are required and which have defaults, and why an absent capability field does not mean the capability is unsupported.
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.
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.