Repository navigation
Fix OAuth refresh resource handling - #2646
FU-max-boop wants to merge 1 commit into
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. |
…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
Summary
AnyHttpUrladds to bare-domain protected resource metadata before choosing the RFC 8707 resource URL.resourceonrefresh_tokengrants while keeping it on authorization-code token exchanges.Fixes #2578
Validation
uv run pytest tests/client/test_auth.py -quv run ruff check src/mcp/client/auth/oauth2.py tests/client/test_auth.pyuv run ruff format --check src/mcp/client/auth/oauth2.py tests/client/test_auth.pygit diff --check