[BUG] [Claude Desktop] Custom OAuth connector sends unsigned/opaque token to resource server

Status Closed — not planned
Maintainer reply None cached
Activity 1 comment · opened Aug 26, 2026 · closed Aug 29, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

When a custom OAuth connector ("Gateway") is configured against a Microsoft Entra ID app registration, the connector's /v1/models discovery call fails with 401 Unauthorized in a tight retry loop, dozens of attempts per second. The resource server's error is not a generic auth failure, it reports the token itself is structurally broken: authentication failure: the token header is malformed: Error(InvalidToken) and, in other attempts, Error(Json(Error("unknown variant none, expected one of HS256... "))).

Inspecting the connector's locally cached credential (decrypted from Claude-3p/config.json's custom3pExternalIdp, which is AES-256-GCM-encrypted with a key wrapped via Windows DPAPI in Local State) shows why: the cached accessToken is not a JWT at all (no . separators, just one opaque string starting PAQABAQIAAAA..., the shape of a Windows broker/WAM token envelope), and the cached idToken is a well-formed JWT but with header {"typ":"JWT","alg":"none"}, explicitly unsigned. The cached tokenUrl is also the legacy v1.0 endpoint (/oauth2/token), not v2.0 (/oauth2/v2.0/token).

What Should Happen?

The connector should acquire a token via a standards-compliant OAuth flow (browser-based authorization code + PKCE against the v2.0 endpoint, or an MSAL configuration that yields a signed JWT for the target resource), and forward that unmodified accessToken as the bearer token. Sending a signed RS256 JWT access token with the same Client ID, Issuer, redirect URI, and scopes, obtained via a manual PKCE flow, was accepted by the resource server with HTTP 200, so the IdP and resource server are not at fault.

Error Messages/Logs

[custom-3p] Gateway /v1/models non-OK { status: 401, body: 'authentication failure: the token header is malformed: Error(InvalidToken)' }
[custom-3p] Gateway /v1/models non-OK { status: 401, body: 'authentication failure: the token header is malformed: Error(Json(Error("unknown variant `none`, expected one of `HS256`, `HS384`, `HS512`, `ES256`, `ES384`, `RS256`, `RS384`, `RS512`, `PS256`, `PS384`, `PS512`, `EdDSA`", line: 1, column: 25)))' }
[custom-3p:idp] credential refreshed silently { id: 'https://login.microsoftonline.com/{tenant}|{clientId}|access_token|api://.../default email offline_access openid profile', idTokenChanged: false }

Steps to Reproduce

  1. In Claude Desktop, configure a custom OAuth connector with:
  • Client ID / Issuer URL for a Microsoft Entra ID app registration (native/public client)
  • Bearer token: Access token
  • Scopes: openid profile email offline_access api://<your-api>/default
  1. Sign in (accepts the native Windows account picker/WAM prompt).
  2. Observe the connection test on /v1/models fail with 401, retrying rapidly.
  3. Inspect %LOCALAPPDATA%\Claude-3p\logs\main.log for the errors above.
  4. Decrypt the cached credential in %LOCALAPPDATA%\Claude-3p\config.json (custom3pExternalIdp key), AES-256-GCM using the key wrapped in Local State via DPAPI, to see the malformed accessToken/idToken shapes.

Claude Model

Not sure / Multiple models

Is this a regression?

I don't know

Last Working Version

I do not know

Claude Code Version

N/A - this is Claude Desktop, not Claude Code CLI; app version 1.37937.1.0

Platform

Anthropic API

Operating System

Windows

Terminal/Shell

Other

Additional Information

This bug is in Claude Desktop (the GUI app), version 1.37937.1.0 (Windows Store/MSIX build), not the Claude Code CLI that this repo/template is normally for. Filing here since it's the only confirmed public Anthropic issue tracker; please redirect internally if there's a better queue. Closest related issue found: #52871 (a different Entra ID/MCP OAuth bug, trailing slash on the resource parameter, not this one).

Workaround in use: bypassing the built-in OAuth flow via the connector's "Helper script" field, pointed at a wrapper script that shells out to an already-working CLI-based token acquisition path, works reliably and returns a valid signed JWT that the resource server accepts.

Happy to provide more detail on the decryption method used to inspect the cached credential, or additional log excerpts, on request.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗