Claude OAuth requires dynamic client registration, making Azure AD/Entra ID integration complex
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:
- 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"]
}
- VS Code reads this and redirects user to Azure AD login
- User authenticates, VS Code receives token, sends it in Authorization header
- 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:
- Implement a fake authorization server endpoint at /.well-known/oauth-authorization-server
- 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"
}
- 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
- Deal with dynamic redirect URIs - Claude uses random ports (54212, 56619, 57411, 59306, 64236, etc.) requiring constant Azure AD app updates
- 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
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
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.
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?
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
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
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.