skip to content

What must the issuer member of a fetched OpenID Provider configuration document match, and why does that comparison matter?

level: middleimportance: should knowfreq 46%

answer

  1. a document only means something once compared
  2. three values, one identity
  3. configured prefix, issuer member, iss claim
  4. identical strings, no normalisation
  5. reject before you store the endpoints

basics

~20 s

The issuer member returned must be identical to the Issuer URL used as the prefix to fetch the document, and identical to the iss claim in ID tokens from that provider. Those three comparisons are what tie a fetched JSON blob to a named issuer.

solid answer

~40 s

A configuration document is fetched at runtime from a URL somebody configured, and on its own it is just JSON. The specification requires two identity comparisons. First, the `issuer` member in the response MUST be identical to the Issuer URL that was used as the prefix to build the request. Second, that same value MUST be identical to the `iss` claim in ID tokens the provider issues. **Identical** means the strings match exactly — no case folding, no trailing-slash tidying, no URL normalisation. Without the first comparison a document served from the wrong place could point `authorization_endpoint` and `token_endpoint` anywhere, and the relying party would send users and codes there. Without the second, a token minted by one issuer could be accepted as though another had signed in the user.

code

json · 7 lines
json
// requested: https://sso.county.example/schools/.well-known/openid-configuration
{
  "issuer": "https://sso.county.example",
  "authorization_endpoint": "https://sso.county.example/authorize",
  "token_endpoint": "https://sso.county.example/token",
  "jwks_uri": "https://sso.county.example/jwks"
}

go deeper

for a junior

Recall that the document names itself in an issuer member, and that the name has to equal the issuer URL you were configured with. Do not treat it as a label you can ignore.

for a middle

Explain the three-way tie: configured Issuer Identifier, the issuer member, and the iss claim in later ID tokens. Say that the comparison is of identical strings, with no normalisation permitted.

for a senior

Demonstrate ordering and failure behaviour: reject before any endpoint is stored, fail startup loudly rather than retrying, and explain why a confidential channel to the host does not substitute for the check.

for a principal

Treat it as the trust anchor of the whole integration. One configured value, checked at two stages, is what stops a runtime-fetched document from redefining where your users and codes are sent.

## Three values, one identity Discovery hands a relying party a JSON object fetched over the network. The document declares endpoints the application will then send its users and its authorization codes to. Nothing about having fetched it makes it a statement about a particular issuer — the comparison does. There are three values in play, and each is only meaningful against the others: 1. **The configured Issuer Identifier** — the one value the application was set up with, and the prefix used to build the request URL. 2. **The `issuer` member** of the document that came back. 3. **The `iss` claim** in ID tokens the provider later issues. The specification requires that the `issuer` member be **identical** to the Issuer URL used as the prefix to fetch the document, and **identical** to the `iss` claim of ID tokens from that issuer. Identical is the strong word: a byte-for-byte string comparison. Not a case-insensitive host match, not a comparison after resolving a trailing slash, not a URL normalisation pass. ## Why the first comparison exists Consider the parents' evening booking system, configured with the local authority's issuer URL. It fetches the document, reads `authorization_endpoint` and `token_endpoint`, and from that moment those addresses drive the whole flow: the browser goes to one, the code goes to the other along with the client credentials. If the fetched document's `issuer` member says something other than the issuer the application was configured with, then one of two things is true — the deployment is pointed at the wrong provider, or the document does not describe the provider the configuration names. Either way the endpoints in it are not the endpoints for the issuer the application intends to trust. The comparison is what ties a fetched document to the issuer you meant, and a relying party that skips it will wire itself up to whatever the document says. The common misreading is that transport security already covers this. It does not. A confidential channel to a host tells you the connection reached the host you named; it says nothing about which issuer the JSON on the other end describes, and a host legitimately carrying several issuers can serve several different documents. ## Why the second comparison exists The second half of the rule reaches forward in time. Every ID token a relying party later validates carries an `iss` claim. That claim must equal the same Issuer Identifier. Without that link, discovery and validation are two unconnected activities: the application would have bootstrapped from one issuer's document and then accepted a token that names a different issuer as the party asserting who signed in. Chained together, the three values form one identity check that spans the whole integration: | Stage | Value produced | Compared against | |---|---|---| | Configuration | Issuer Identifier | — | | Discovery response | `issuer` member | the configured Issuer Identifier | | Token validation | `iss` claim | the same Issuer Identifier | ## Getting the comparison itself right - **Compare the strings, not your idea of the URLs.** `https://sso.county.example/schools` and `https://sso.county.example/schools/` are different strings and therefore a mismatch; so are two spellings that differ only in host case. - **Compare before you use anything.** Reject and stop on a mismatch. Storing the endpoints first and validating afterwards means a mismatched document has already configured the application. - **Compare against the configured value, not against itself.** Reading `issuer` out of the document and then checking `iss` against it makes the document the authority for its own name, which removes the check entirely. - **Fail loudly.** A mismatch is a configuration or trust fault, not a transient error to retry past. ## Where this stops This is the OpenID Provider configuration document's own rule. The neighbouring OAuth authorization-server metadata document carries an equivalent requirement of its own shape, and the response-integrity parameter that tells a relying party which authorization server answered a particular authorization request is a separate mechanism again, solving a different problem on a different message. What lives here is narrow and worth knowing exactly: the document says who it is, and you check that against who you asked.

  • The configured issuer ends without a slash and the issuer member ends with one. Is that a match?
    No. The requirement is that the values be identical, and those are different strings. It is tempting to normalise the two before comparing, but normalisation is exactly what the rule excludes — it would let a family of near-miss spellings all satisfy a check whose whole value is that only one spelling does.
  • Why is comparing the iss claim against the issuer member read from the document not enough?
    Because it makes the document the authority for its own name. Both values then come from the same fetched source, so a document describing the wrong issuer agrees with tokens from that wrong issuer and the check passes. The anchor has to be the Issuer Identifier the application was configured with, independently of anything fetched.
  • A host serves several issuers. What does a successful TLS connection to it tell you?
    Only that you reached that host. The host may legitimately publish many configuration documents under many paths, so the connection cannot distinguish the issuer you meant from a neighbouring one on the same host. That is precisely the deployment the concatenation rule was designed for, and precisely why the issuer comparison is stated separately.

A reply arrives from the postal address you wrote to, but the letterhead names a different organisation. The envelope proves where it came from; only reading the letterhead tells you who is claiming to answer.

saying these in an interview costs you the question

  • Treats the issuer member as informational metadata
  • Normalises case or trailing slashes before comparing
  • Assumes a confidential channel makes the comparison unnecessary
  • Compares the iss claim only against the document, never against configuration
  • Stores the endpoints first and validates the issuer afterwards
  • Thinks a matching hostname is a matching issuer