claude-code icon indicating copy to clipboard operation
claude-code copied to clipboard

Claude OAuth requires dynamic client registration, making Azure AD/Entra ID integration complex

Open JayDoubleu opened this issue 6 months ago • 10 comments

Issue Description:

I've been working on implementing an MCP server with OAuth 2.1 authentication using Azure Entra ID (formerly Azure AD).

With VS Code Desktop - Simple and Working

VS Code's implementation is straightforward:

  1. MCP server provides /.well-known/oauth-protected-resource:
{
  "resource": "https://my-mcp-function.azurewebsites.net",
  "authorization_servers": ["https://login.microsoftonline.com/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/v2.0"],
  "bearer_methods_supported": ["header"]
}
  1. VS Code reads this and redirects user to Azure AD login
  2. User authenticates, VS Code receives token, sends it in Authorization header
  3. It just works - No extra endpoints needed, uses standard Azure AD OAuth flow

With Claude Apps - Complex Workarounds Required

To make the same MCP server work with Claude (Code/Desktop/ai), I had to:

  1. Implement a fake authorization server endpoint at /.well-known/oauth-authorization-server
  2. Create a dynamic client registration endpoint at /register that returns:
  {
    "client_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "client_name": "Claude Code (test)",
    "redirect_uris": ["http://localhost:64236/callback"],
    "grant_types": ["authorization_code", "refresh_token"],
    "response_types": ["code"],
    "token_endpoint_auth_method": "none",
    "application_type": "native",
    "scope": "openid profile email offline_access"
  }
  1. Handle the fact that Azure AD URLs need /oauth2 in the path: - VS Code works with: https://login.microsoftonline.com/{tenant}/v2.0/authorize - Claude needs: https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize
  2. Deal with dynamic redirect URIs - Claude uses random ports (54212, 56619, 57411, 59306, 64236, etc.) requiring constant Azure AD app updates
  3. Even after all this, still getting errors:

AADSTS70011: The provided request must include a 'scope' input parameter. The provided value for the input parameter 'scope' is not valid.

The Problem

Azure AD (and many enterprise OAuth providers) don't support dynamic client registration. They require pre-registered applications with fixed redirect URIs and client IDs.

Creating fake registration endpoints and trying to proxy the OAuth flow adds significant complexity compared to VS Code's approach, and still doesn't fully work due to how Claude constructs the authorization requests.

I believe this client oauth2 implementation is also causing github's official remote MCP server to be incompatible with Claude apps https://github.com/github/github-mcp-server/issues/549

JayDoubleu avatar Jun 24 '25 11:06 JayDoubleu

I believe this client oauth2 implementation is also causing github's official remote MCP server to be incompatible with Claude apps https://github.com/github/github-mcp-server/issues/549

Yep, as mentioned here, Github MCP Server does not support Dynamic Client Registration

https://github.com/github/github-mcp-server/blob/main/docs/host-integration.md#connecting-to-the-remote-github-mcp-server

mculp avatar Jun 27 '25 18:06 mculp

In my tests, Claude.ai doesn't perform the register call even if dynamic client registration is enabled. Instead, the authorize endpoint is called directly, which by default fails.

scthi avatar Jun 28 '25 07:06 scthi

What was the purpose of dynamic client registration for Claude (Desktop et al)? It's a very unusual requirement. Dynamic client registration (rfc7591) is one of those specs that I thought died out due to impracticality and low usefulness 😆 Jokes aside (it is a useful spec, but I hardly see it in practice), does Claude Code/Desktop support an initial authentication mechanism for DCR?

jnicholls avatar Jul 24 '25 17:07 jnicholls

What was the purpose of dynamic client registration for Claude (Desktop et al)? It's a very unusual requirement.

It's part of the MCP spec: https://modelcontextprotocol.io/specification/2025-03-26/basic/authorization#dynamic-client-registration

S-Luiten avatar Aug 06 '25 09:08 S-Luiten

What was the purpose of dynamic client registration for Claude (Desktop et al)? It's a very unusual requirement.

It's part of the MCP spec: https://modelcontextprotocol.io/specification/2025-03-26/basic/authorization#dynamic-client-registration

it is a SHOULD though

saucoide avatar Aug 10 '25 15:08 saucoide

It's strange that this is not being fixed. It seems clear now that many MCP servers don't and won't support DCR. Why not allow client id/secret type of registration? Or the even simpler PAT/bearer token authentication? Like xcode configuration

  {
    "servers": {
        "github": {
            "url": "https://api.githubcopilot.com/mcp/",
            "requestInit": {
                "headers": {
                    "Authorization": "Bearer YOUR_GITHUB_PAT"
                }
            }
        }
    }
  }

That should be pretty straightforward and get things moving while world is becoming perfect.

akostadinov avatar Oct 14 '25 17:10 akostadinov