fix: classify upstream errors correctly instead of returning 500#42
Merged
mattzcarey merged 2 commits intomainfrom Feb 23, 2026
Merged
fix: classify upstream errors correctly instead of returning 500#42mattzcarey merged 2 commits intomainfrom
mattzcarey merged 2 commits intomainfrom
Conversation
Upstream 4xx from Cloudflare OAuth and API endpoints were thrown as generic Error objects, caught by route handlers, and returned as 500 Server Error pages. This violates the MCP auth spec which requires 401 for invalid tokens, 403 for insufficient permissions, and 400 for malformed requests. Changes: - Preserve upstream HTTP status codes (400/401/403/429) through OAuthError with RFC-precise error codes (invalid_grant, invalid_token, insufficient_scope, etc.) - Map upstream 5xx to 502 Bad Gateway - Replace generic Error throws in parseRedirectApproval with typed OAuthError instances - Forward OAuthError statusCode through renderErrorPage and toHtmlResponse - Add error correlation IDs to unexpected error responses for log tracing - Remove raw error message leakage from client-facing responses - Respect OAuthError status in API token mode catch block
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Reports of frequent 5xx responses from the token and authorization endpoints revealed that upstream 4xx errors from Cloudflare's OAuth and API services were being swallowed as generic
Errorobjects and returned as 500 Server Error pages. This violates the MCP auth spec which requires correct status codes:This PR ports the same class of fixes from cloudflare/mcp-server-cloudflare#294 to the new MCP server.
Changes (4 files, +83 / -21)
src/auth/cloudflare-auth.tsgetAuthTokenandrefreshAuthTokennow throwOAuthErrorwith the upstream status code instead of genericErrorthrowUpstreamErrorhelper that maps upstream HTTP status to RFC-precise OAuth error codes:invalid_grant, 401 →invalid_client, 403 →unauthorized_client, 429 →temporarily_unavailable, 5xx →server_error(502)console.errorbut never sent to clientssrc/auth/oauth-handler.tsgetUserAndAccountsnow checksresponse.okbefore parsing and throwsOAuthErrorwith RFC 6750 bearer token error codes:invalid_token, 403 →insufficient_scope, 429 →temporarily_unavailable, 5xx →server_error(502)ErrortoOAuthError('invalid_token', ..., 401)crypto.randomUUID()) to unexpected error responses — the ID appears in both the client-facing error page andconsole.errorfor log tracinge.messagefrom client-facing error details to prevent information leakagesrc/auth/workers-oauth-utils.tsrenderErrorPageaccepts optionalstatusparameter (default 400, backward-compatible)OAuthError.toHtmlResponse()now forwardsthis.statusCodetorenderErrorPageinvalid_grant,invalid_client,invalid_token,insufficient_scopeto the HTML error title mapparseRedirectApprovalthrowsOAuthErrorinstead of genericErrorfor all validation failures:src/auth/api-token-mode.tsOAuthErrorand usestoResponse()(JSON) with the correct status codee.messageleakage)What this does NOT change
isError: true)OAuthErrorTest plan
npm run checkpasses (format, lint, typecheck, 69 tests)invalid_token(not 500)invalid_request(not 500)