modelcontextprotocol / modelcontextprotocol/python-sdk

OAuth token refresh hits the wrong endpoint when the auth server lives under a path

Offen
#3,240 2 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

P1 v1 v2
Vorherrschende Sprache
Python
Sterne
24.3k
Forks
4k
Ø Merge
1 T. 1 Std.
Gemergte PRs (30 T.)
31

Beschreibung

Ran into this with a hosted MCP server whose authorization server isn't at the origin root — token endpoint is https://host/oauth2/api/v1/token, not https://host/token.

If a client starts up with a cached-but-expired access token (+ refresh token) and hasn't done discovery yet, async_auth_flow refreshes at the very top — before any 401/metadata discovery. So oauth_metadata is None and _refresh_token uses the fallback urljoin(get_authorization_base_url(server_url), "/token"), i.e. just {scheme}://{netloc}/token. That 404s, _handle_refresh_response clears the tokens, and the flow drops to full interactive auth — which a headless/gateway client can't do. So the server silently disconnects every time the access token expires (mine are 5 min, so… constantly).

Same path-stripping fallback is in _get_token_endpoint, _perform_authorization_code_grant (/authorize) and DCR (/register) — refresh is just the one that bites silently.

Repro (roughly):

  • MCP server whose AS metadata puts token_endpoint under a path, not {origin}/token
  • log in normally so tokens get cached
  • let the access token expire (or clear the expiry), reconnect with a fresh provider
  • watch the refresh POST go to https://host/token → 404 → "Token refresh failed" → tokens cleared → it tries to open a browser

Fix looks like: discover metadata before the eager refresh (or stop dropping the issuer path in the fallback). Happy to PR — have a branch that pulls the PRM/ASM discovery out of the 401 branch and runs it before the refresh.

(used some AI help digging into this)

Beitragsleitfaden

Beitragsleitfaden öffnen

Erste Schritte

  1. Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
  3. Forke das Repository und arbeite in einem Branch.
  4. Öffne einen Pull Request, der die Issue-Nummer nennt.

Rechercherichtung

Beginne damit, async_auth_flow und seinen Eager-Refresh-Pfad bis zu _refresh_token nachzuverfolgen, und vergleiche dann das Fallback-Verhalten in _get_token_endpoint, _perform_authorization_code_grant und DCR. Reproduziere das Szenario eines zwischengespeicherten abgelaufenen Tokens gegenüber einem Authorization Server, dessen Metadatenendpunkte einen Pfad enthalten. Als erledigt gilt die Aufgabe, wenn die Aktualisierung den ermittelten Token-Endpunkt verwendet und weder gültige Tokens löscht noch auf interaktive Authentifizierung zurückfällt.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
python
Bereich
api, authentication
Issue-Typ
Bug
Schwierigkeit
4/5
Geschätzter Aufwand
3-5 Tage
Aktivitätsstatus
Ruhig
Klarheit
Klar beschrieben
Anfängerfreundlichkeit
48/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.