auth: validate unadvertised RFC 9207 iss instead of rejecting it (#1187)
## Summary Fixes #1152. Sentry, Linear, and Notion omit `authorization_response_iss_parameter_supported` from their authorization-server metadata. Sentry still sends a correct `iss` in the authorization response, so sign-in fails after the browser step: the user has already consented and an authorization code has been issued, but `validateIssuerResponse` rejects the exchange solely because the server did not advertise RFC 9207 support. RFC 9207 §2.4 says clients MUST extract and compare `iss` when the parameter is present. §2.4 also notes that clients SHOULD discard an unadvertised `iss`, but that is a recommendation and local policy may accept servers that send `iss` without advertising. Validating a matching `iss` is interoperable with those hosted MCP servers and still catches mix-up attacks: a wrong `iss` is rejected whether or not support was advertised. When `iss` is present, this change always compares it to the expected issuer (simple string equality). A match is accepted even if the server did not advertise support. A mismatch still returns `authorization response issuer %q does not match expected issuer %q`. Absence of `iss` remains an error only when the server advertised support. ## Test plan - [x] `go test ./auth/ -run TestValidateIssuerResponse -count=1` - [x] `go test ./auth/...` New `TestValidateIssuerResponse` cases: - `UnadvertisedIssCorrect`: `iss == expectedIssuer`, `issSupported == false` → no error - `UnadvertisedIssWrong`: `iss == "https://attacker.example.com"`, `issSupported == false` → error containing `does not match expected issuer` Existing advertised+match / advertised+mismatch / missing-iss cases are unchanged. --------- Co-authored-by: Guglielmo Colombo <guglielmoc@google.com>
This commit is contained in:
parent
810e6cb751
commit
32404652e6
1 changed files with 173 additions and 16 deletions
|
|
@ -97,6 +97,11 @@ type Config struct {
|
|||
// IssueRefreshToken, if true, includes a refresh_token in token responses and
|
||||
// enables grant_type=refresh_token at the /token endpoint.
|
||||
IssueRefreshToken bool
|
||||
// UnadvertiseIssParameter, if true, omits
|
||||
// authorization_response_iss_parameter_supported from metadata while the
|
||||
// authorize endpoint still includes iss. Used to test local policy for
|
||||
// unadvertised RFC 9207 iss.
|
||||
UnadvertiseIssParameter bool
|
||||
}
|
||||
|
||||
// testRefreshToken is the refresh token issued and accepted by the fake server
|
||||
|
|
@ -199,8 +204,9 @@ func (s *FakeAuthorizationServer) handleMetadata(w http.ResponseWriter, r *http.
|
|||
CodeChallengeMethodsSupported: []string{"S256"},
|
||||
ClientIDMetadataDocumentSupported: cimdSupported,
|
||||
TokenEndpointAuthMethodsSupported: []string{"client_secret_post", "client_secret_basic"},
|
||||
// Advertise RFC 9207 support: the authorize endpoint includes "iss" in responses.
|
||||
AuthorizationResponseIssParameterSupported: true,
|
||||
// Advertise RFC 9207 support unless UnadvertiseIssParameter is set:
|
||||
// the authorize endpoint still includes "iss" in responses either way.
|
||||
AuthorizationResponseIssParameterSupported: !s.config.UnadvertiseIssParameter,
|
||||
}
|
||||
// Set CORS headers for cross-origin client discovery.
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
|
|
|
|||
Loading…
Reference in a new issue