| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
…ience IdentityAssertionGrantProvider passed authorizationServerUrl.ToString() as the RFC 8693 audience. Uri.ToString() appends a trailing slash to an empty path, so the common case (https://auth.example.com, whose metadata advertises the issuer without a slash) sent an audience that did not match the issuer. Use the issuer from the authorization server metadata already fetched in step 1, falling back to the configured URL when the metadata omits it. Fixes modelcontextprotocol#1617 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Before making the discovered issuer authoritative for the JAG audience, I think this flow needs the RFC 8414 issuer-identity validation that the SDK's regular OAuth path already performs. IdentityAssertionGrant.DiscoverAuthServerMetadataAsync() currently returns the metadata without checking that metadata.Issuer is identical to the issuer URL used to construct the well-known request. This PR then uses that unvalidated field as the token-exchange audience. The new theory test actually makes the mismatch observable: for an authorization server URL of https://auth.example.com/, an advertised issuer of https://auth.example.com/tenant is accepted and becomes the audience. RFC 8414 §3.3 requires the returned issuer to be identical to the issuer identifier used for discovery; the main ClientOAuthProvider has an explicit check for this. Because this PR changes the audience from the caller-selected AS URL to metadata-controlled input, I would validate the issuer first and make the mismatched-issuer case fail rather than assert it as supported behavior. AI-assisted review; checked the current head and both metadata-discovery implementations before posting. |
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
Fixes #1617
Problem
IdentityAssertionGrantProvider sends authorizationServerUrl.ToString() as the audience of the RFC 8693 token exchange at the IdP. That value isn't guaranteed to match the MCP authorization server's issuer identifier, and in the most common setup it doesn't: new Uri("https://auth.example.com").ToString() returns "https://auth.example.com/", while the metadata advertises "issuer": "https://auth.example.com". An IdP that compares the audience against the issuer exactly will reject the exchange.
Fix
Use the issuer from the authorization server metadata that step 1 of the flow already fetches (mcpAuthMetadata). Issuer.OriginalString is used so the value is sent exactly as published, since Uri.ToString() would reintroduce the same trailing-slash normalization. This matches how ClientOAuthProvider compares issuers, and the direction taken by the Python SDK (override_audience_with_issuer, modelcontextprotocol/python-sdk#1721).
If the metadata doesn't include an issuer, it falls back to the previous behavior, so nothing that works today changes.
Scope is limited to the audience, as described in the issue. resource is left as is.
Tests
Added IdentityAssertionGrantProvider_UsesDiscoveredIssuerAsJagAudience (theory), which reads the audience form field sent to the IdP:
The first two cases fail on main (actual: https://auth.example.com/) and pass with this change. IdentityAssertionGrantTests and the AspNetCore OAuth integration tests pass locally on net10.0, net9.0, net8.0 and net472. The full ModelContextProtocol.Tests suite also passes on net10.0 (2399 tests, 6 skipped because they need an OpenAI key).
🤖 Generated with Claude Code