Interactive OAuth flow is aborted by DiscoverProbeTimeout during dual-path connect, then fails with an authorization state mismatch
@PederHP ci sta già lavorando.
Dal 20/8/2026.
Valutazione
Questa issue non è ancora stata valutata.
Descrizione
Summary
When connecting to an OAuth-protected server with the default dual-path connect (ProtocolVersion unset), an interactive authorization flow started by the server/discover probe's 401 challenge is silently destroyed by McpClientOptions.DiscoverProbeTimeout (default 5s), and the connect then reliably fails with:
ModelContextProtocol.McpException: Failed to handle unauthorized response with 'Bearer' scheme. The authorization response state did not match the state sent in the authorization request.
Sequence (observed against a production MCP server, SDK 2.2.0)
- The client sends the
server/discoverprobe. The server answers 401, which entersClientOAuthProvider: metadata discovery, DCR, thenAuthorizationCallbackHandleris invoked. The host presents the authorization URL (stateS1) to the user, who starts logging in. - After 5 seconds,
DiscoverProbeTimeoutelapses. This timeout exists for servers that silently drop unknown methods — but here the cancellation propagates throughHandleUnauthorizedResponseAsyncinto the pending interactive flow and aborts it, even though the user is mid-login in a browser the SDK cannot close. - The client falls back to
initialize, which draws another 401 and starts a second interactive flow with a fresh stateS2and PKCE verifier. The host has no new popup to show — the user is still completing flow 1. - The user finishes logging in; the redirect arrives carrying
S1. The second flow expectsS2→ValidateStateResponsethrows the state-mismatch error above. The user-approved authorization code is unusable by flow 2 anyway (different PKCE verifier), so there is no way to recover the flow the user actually completed.
A second, related problem: the whole interactive login is bounded by InitializationTimeout (default 60s), which a real login (with MFA etc.) easily exceeds. That part is at least configurable, but nothing in the docs points hosts at it.
Expected behavior
Canceling the request whose challenge started an interactive authorization should not abort the flow itself — the user-facing browser flow is already in progress and only one flow can ever match the redirect the user completes. A subsequent challenge (from the initialize fallback, or any concurrent request) should join the in-flight flow and reuse its result instead of starting a competing flow the user never sees.
Suggested fix
In ClientOAuthProvider, memoize the in-flight authorization-code flow and detach it from the triggering request's cancellation token (bounding it by provider disposal instead); challenge handlers await it with their own token via Task.WaitAsync. The existing _tokenAcquisitionLock + cached-token re-check already handles the "another caller acquired the token" case once the flow survives.
Docs for DiscoverProbeTimeout / InitializationTimeout should also mention the interactive-authorization interplay.
I have a PR ready with this change plus regression tests (deterministic cancellation-survival test, an end-to-end probe-timeout scenario test, and a transport-dispose cancellation test).
Workaround (current releases)
For interactive connects, set DiscoverProbeTimeout = Timeout.InfiniteTimeSpan and raise InitializationTimeout above the host's authorization window.
- Lingua principale
- C#
- Stelle
- 4.5k
- Fork
- 814
- Merge medio
- 9g 19h
- PR unite (30g)
- 4
Guida per i contributori
Apri la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di modelcontextprotocol/csharp-sdk
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
modelcontextprotocol/csharp-sdk#1867 ·
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 88/100
modelcontextprotocol/csharp-sdk#1840 · 1 commento ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 84/100
modelcontextprotocol/csharp-sdk#1836 ·
-
enhancement needs confirmation
Difficoltà 2/5 1-3 ore Idoneità per principianti 64/100
modelcontextprotocol/csharp-sdk#678 · 1 commento ·
-
enhancement needs confirmation P3 ready for work
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
modelcontextprotocol/csharp-sdk#515 · 6 commenti · 3 reazioni ·
Tutte le issue di modelcontextprotocol/csharp-sdk
Issue simili
-
[Feat] 조합 영역 구분선 개선 Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
-
type/automation type/tech-debt
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 88/100
-
t/bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
-
ci-failure-cause test-failure
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100