modelcontextprotocol / modelcontextprotocol/python-sdk

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

Aberta
#3,240 2 comentários 0 reações 0 responsáveis Ver no GitHub

Ninguém assumiu esta issue ainda.

P1 v1 v2
Linguagem predominante
Python
Estrelas
24.3k
Forks
4k
Merge médio
1d 1h
PRs com merge (30d)
31

Descrição

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)

Guia de contribuição

Abrir o guia de contribuição

Primeiros passos

  1. Leia a issue inteira e depois o guia de contribuição do projeto.
  2. Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
  3. Faça um fork do repositório e trabalhe em uma branch.
  4. Abra um pull request que referencie o número da issue.

Direção de pesquisa

Comece rastreando async_auth_flow e seu caminho de eager refresh até _refresh_token e, em seguida, compare o comportamento de fallback em _get_token_endpoint, _perform_authorization_code_grant e DCR. Reproduza o cenário de um token expirado em cache diante de um authorization server cujos endpoints de metadados incluem um caminho. Considera-se concluído quando o refresh usa o endpoint de token descoberto e não limpa tokens válidos nem recorre à autenticação interativa.

Escrita pelo modelo de indexação a partir do texto da issue.

Avaliação

Stack de tecnologia
python
Domínio
api, authentication
Tipo de issue
Bug
Dificuldade
4/5
Tempo estimado
3-5 dias
Status de atividade
Pouca atividade
Clareza
Claramente especificada
Facilidade para iniciantes
48/100

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.