fix(oauth): omit resource param on token refresh - #2645
Conversation
|
Thanks for the PR. Closing in favor of #2590, which was opened first (May 13) and covers the same two fixes — dropping One substantive difference worth noting: this PR strips the slash with If you spot anything #2590 misses, a review there would be welcome. |
|
Thanks, that makes sense. I checked #2590 and it covers both changes; its root-only normalization is the better behavior for exact resource identifiers. I don't see anything from this PR to carry over. |
…railing slash from PRM resource Two compounding bugs broke silent token refresh against Microsoft Entra ID v2.0 (AADSTS9010010), causing MCP servers using Entra OAuth to lose authentication after ~1 hour: - _refresh_token() sent the RFC 8707 resource parameter on refresh_token grants, which Entra v2.0 strictly rejects since March 2026. The parameter is now omitted from refresh requests. - Pydantic's AnyHttpUrl normalizes bare-domain PRM resource URLs to include a trailing slash, so the resource audience never matched the IdP app registration. get_resource_url() now strips the slash, but only when the path is exactly "/" with no query or fragment - RFC 9728 requires exact-string identity, so intentional trailing slashes on deeper paths are preserved. Implements the approach maintainers endorsed when consolidating earlier attempts (modelcontextprotocol#2590, since closed unmerged; see discussion on modelcontextprotocol#2645/modelcontextprotocol#2646). Fixes modelcontextprotocol#2578
…railing slash from PRM resource Two compounding bugs broke silent token refresh against Microsoft Entra ID v2.0 (AADSTS9010010), causing MCP servers using Entra OAuth to lose authentication after ~1 hour: - _refresh_token() sent the RFC 8707 resource parameter on refresh_token grants, which Entra v2.0 strictly rejects since March 2026. The parameter is now omitted from refresh requests. - Pydantic's AnyHttpUrl normalizes bare-domain PRM resource URLs to include a trailing slash, so the resource audience never matched the IdP app registration. get_resource_url() now strips the slash, but only when the path is exactly "/" with no query or fragment - RFC 9728 requires exact-string identity, so intentional trailing slashes on deeper paths are preserved. Implements the approach maintainers endorsed when consolidating earlier attempts (modelcontextprotocol#2590, since closed unmerged; see discussion on modelcontextprotocol#2645/modelcontextprotocol#2646). Fixes modelcontextprotocol#2578
Fixes #2578.
Entra ID v2.0 rejects RFC 8707
esource on refresh token requests, and Pydantic AnyHttpUrl normalizes bare-domain URLs with a trailing slash.
Changes:
esource in
efresh_token grant requests.
Tests: