Salesforce MCP OAuth (PKCE) fails with "invalid code verifier" on every attempt

Resolved 💬 2 comments Opened Jun 25, 2026 by shailendragit91 Closed Jun 28, 2026

Environment

  • Claude Code VS Code extension: 2.1.191 (also reproduced on 2.1.185)
  • agent-sdk: 0.3.191
  • OS: macOS (Darwin 25.5.0, arm64)
  • MCP server config (.mcp.json):

``json
"salesforce-sandbox-mcp": {
"type": "http",
"url": "https://api.salesforce.com/platform/mcp/v1/platform/sobject-all",
"oauth": {
"clientId": "<redacted Connected App / External Client App client ID>",
"callbackPort": 8080,
"scopes": "api mcp_api refresh_token"
}
}
``

Steps to reproduce

  1. Configure a Salesforce "Hosted MCP" server in .mcp.json as above, pointing at https://api.salesforce.com/platform/mcp/v1/platform/sobject-all.
  2. Run /mcp, select the Salesforce server, click authenticate.
  3. Browser opens Salesforce login, user authenticates, consents, and is redirected to http://localhost:8080/callback — browser tab shows "Authentication successful" and auto-closes within ~1 second.
  4. Claude's UI stays stuck on "Completing authentication in browser…" indefinitely; no error surfaces in the UI (only visible in the extension's debug log).

Expected

MCP server authenticates successfully and tools become available.

Actual

Auth never completes. Extension log (Claude VSCode.log) shows the token exchange failing, reproduced consistently across many attempts over ~40 minutes:

[DEBUG] MCP server "salesforce-sandbox-mcp": Completing auth flow with authorization code
[DEBUG] MCP server "salesforce-sandbox-mcp": Returning cached discovery state (...)
[DEBUG] MCP server "salesforce-sandbox-mcp": Using pre-configured client ID
[DEBUG] MCP server "salesforce-sandbox-mcp": Using scope from metadata: mcp_api refresh_token
[DEBUG] MCP server "salesforce-sandbox-mcp": Returning code verifier
[DEBUG] MCP server "salesforce-sandbox-mcp": Using pre-configured client ID
[DEBUG] MCP server "salesforce-sandbox-mcp": Invalidated credentials (scope: tokens)
[DEBUG] MCP server "salesforce-sandbox-mcp": Returning cached discovery state (...)
[DEBUG] MCP server "salesforce-sandbox-mcp": Saving discovery state (...)
[DEBUG] MCP server "salesforce-sandbox-mcp": Using pre-configured client ID
[DEBUG] MCP server "salesforce-sandbox-mcp": Using scope from metadata: mcp_api refresh_token
[DEBUG] MCP server "salesforce-sandbox-mcp": Returning code verifier
[DEBUG] MCP server "salesforce-sandbox-mcp": Using pre-configured client ID
[DEBUG] MCP server "salesforce-sandbox-mcp": Error during auth completion: invalid code verifier
[ERROR] MCP OAuth failed for salesforce-sandbox-mcp: invalid code verifier

One attempt in the same session instead failed with a different error from what looks like the same broken exchange path:

[DEBUG] MCP server "salesforce-sandbox-mcp": Error during auth completion: invalid client credentials
[ERROR] MCP OAuth failed for salesforce-sandbox-mcp: invalid client credentials

Notable: the "complete auth" sequence runs through verifier/discovery retrieval twice for a single authorization code, with an unexplained Invalidated credentials (scope: tokens) event sandwiched in between. The scope is also silently narrowed from the configured api mcp_api refresh_token down to mcp_api refresh_token (per the auth server's metadata) between the two passes. The final POST to Salesforce's token endpoint is then rejected — either on the PKCE verifier or on client credentials depending on timing — consistent with the client reusing a single-use authorization code twice, or recomputing/refetching a verifier that no longer matches the original code_challenge sent in the authorize request.

Ruled out

  • Connected App / External Client App config: callback URL is correctly registered (browser redirect to localhost:8080/callback succeeds every time, browser shows "Authentication successful" and auto-closes); confirmed "Require Secret for Web Server Flow" disabled and refresh_token/offline_access scope enabled on the app — no change in behavior.
  • Extension version: reproduced identically on both 2.1.185 and 2.1.191.
  • Local port conflicts: port 8080 confirmed free before each attempt.
  • Stale local state: repro is consistent across many fresh /mcp reauthenticate attempts with cleared stored tokens each time (log shows "Cleared stored tokens" at the start of each attempt).

Impact

Any MCP server using PKCE + an auth server that returns a narrower scope in its OAuth metadata than what's requested (as Salesforce's does here) appears unable to complete authentication at all. No error is surfaced in the UI — it just hangs on "Completing authentication in browser…" forever with a "Needs Auth" badge, which makes this very hard for end users to diagnose without pulling extension debug logs.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗