Skip to content

refresh_token grant advertised but not implemented (always 500s); authorization_code exchange never issues a refresh token #404

Description

@bbasketballer75

Environment: @1mcp/agent v0.34.4, Node v22.14.0, Windows 11

Summary: GET /.well-known/oauth-authorization-server advertises "grant_types_supported":["authorization_code","refresh_token"], and Dynamic Client Registration accepts clients that request refresh_token in their grant_types. But exchangeAuthorizationCode() (build/auth/sdkOAuthServerProvider.js:254-303) never includes a refresh_token field in its response, and exchangeRefreshToken() (same file, lines 304-309) is unconditional:

async exchangeRefreshToken(_client, _refreshToken, _scopes, _resource) {
    throw new Error('Refresh tokens not supported');
}

This plain Error isn't one of the SDK's OAuthError subclasses, so it surfaces to clients as a raw 500 Internal Server Error instead of a spec-compliant 400 invalid_grant. Any OAuth client that follows the advertised metadata and later attempts a token refresh (which any client holding a token past its TTL will eventually need to do) gets an opaque server error instead of a clean re-auth signal.

Steps to reproduce (pure curl, no client library needed):

POST /register   {token_endpoint_auth_method:"none", grant_types:["authorization_code","refresh_token"]}
→ 201, client_id issued (no client_secret, as expected for a public/PKCE client)

GET /authorize?client_id=...&code_challenge=...&code_challenge_method=S256&redirect_uri=...&scope=...
→ 200, consent page HTML

POST /oauth/consent  auth_request_id=...&action=approve&scopes=...
→ 302 Location: <redirect_uri>?code=...&state=...

POST /token  grant_type=authorization_code, code=..., code_verifier=..., client_id=... (no client_secret)
→ 200 OK, access_token issued — but no refresh_token field in the response at all

POST /token  grant_type=refresh_token, refresh_token=<any value>, client_id=...
→ 500 Internal Server Error   {"error":"server_error","error_description":"Internal Server Error"}

Suggested fix: Either implement exchangeRefreshToken properly (store/rotate a refresh token issued during exchangeAuthorizationCode, and throw the SDK's InvalidGrantError for bad/missing tokens so it maps to a proper 400 response), or if refresh is intentionally unsupported, remove refresh_token from grant_types_supported in the discovery metadata and from registration echoes, so clients don't rely on a capability that silently fails with an opaque 500.


Found while debugging why OpenAI Codex CLI's OAuth session against a local 1mcp instance stopped working shortly after initial authorization — its client library reported a generic "grant not found" style error on refresh, which traces back to this.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingready-for-agentFully specified, ready for an AFK agent

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions