Verify the discovery document's issuer in the IdP resolver #59

Open
opened 2026-09-19 01:23:17 +00:00 by ginjiruu · 0 comments
Owner

Context

Security architecture review, 18 Sep 2026 (candidate 5, "Worth exploring"). The IdP resolver fetches <issuer>/.well-known/openid-configuration and takes token_endpoint, authorization_endpoint, and jwks_uri from the document — but never verifies that the document's issuer field equals the requested issuer URL, as RFC 8414 §3 and OIDC Discovery require. The bridge's trust anchor is TLS to the issuer host, so exploiting this needs issuer-host compromise; but the consequence of a bad document is asymmetric: a Confidential client's client secret is POSTed to the document's token_endpoint, and JWKS is fetched from the document's jwks_uri. A misconfigured or hostile document on a shared/multi-tenant IdP host can redirect the bridge's secret-bearing traffic. The id_token iss check against the CRD's issuer URL (which the serving path does correctly) stops session forgery, but not endpoint redirection.

What to build

Add issuer to the discovery struct and require doc.Issuer == issuerURL (with the RFC's trailing-slash normalization) in the document validation. A mismatch is a resolve failure — the existing keep-last-good behaviour still applies, so a transient bad document never blanks the last-good signing keys or endpoints.

Acceptance criteria

  • The discovery struct parses issuer; validation requires it to equal the requested issuer URL (trailing-slash normalized)
  • A mismatched issuer is a resolve failure — test with a fake discovery server returning a mismatched issuer
  • Keep-last-good on resolve failure still applies (a mismatch does not blank the last-good state)
  • Existing idp resolver tests stay green

Blocked by

  • None — can start immediately
## Context Security architecture review, 18 Sep 2026 (candidate 5, "Worth exploring"). The IdP resolver fetches `<issuer>/.well-known/openid-configuration` and takes `token_endpoint`, `authorization_endpoint`, and `jwks_uri` from the document — but never verifies that the document's `issuer` field equals the requested issuer URL, as RFC 8414 §3 and OIDC Discovery require. The bridge's trust anchor is TLS to the issuer host, so exploiting this needs issuer-host compromise; but the consequence of a bad document is asymmetric: a Confidential client's client secret is POSTed to the document's `token_endpoint`, and JWKS is fetched from the document's `jwks_uri`. A misconfigured or hostile document on a shared/multi-tenant IdP host can redirect the bridge's secret-bearing traffic. The id_token `iss` check against the CRD's issuer URL (which the serving path does correctly) stops session forgery, but not endpoint redirection. ## What to build Add `issuer` to the discovery struct and require `doc.Issuer == issuerURL` (with the RFC's trailing-slash normalization) in the document validation. A mismatch is a resolve failure — the existing keep-last-good behaviour still applies, so a transient bad document never blanks the last-good signing keys or endpoints. ## Acceptance criteria - [ ] The discovery struct parses `issuer`; validation requires it to equal the requested issuer URL (trailing-slash normalized) - [ ] A mismatched issuer is a resolve failure — test with a fake discovery server returning a mismatched issuer - [ ] Keep-last-good on resolve failure still applies (a mismatch does not blank the last-good state) - [ ] Existing idp resolver tests stay green ## Blocked by - None — can start immediately
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lab/authz-bridge#59
No description provided.