Skip to content

CIMD rejects VS Code's client-metadata document over unsupported device_code grant type #6290

Description

@danbarr

Summary

The embedded authorization server's CIMD support (#4825) rejects VS Code's real-world client-metadata document because it lists urn:ietf:params:oauth:grant-type:device_code in grant_types alongside authorization_code and refresh_token. The grant-types validator hard-rejects any document containing a grant type outside a fixed allowlist, instead of ignoring/filtering grant types the server doesn't need for the CIMD-driven flow. The end result is a generic invalid_client error that gives no indication of the real cause.

VS Code is the client this feature was explicitly designed for (#4825 background section), so this breaks CIMD for its primary intended consumer.

Reproduction

  1. Deploy a VirtualMCPServer (or any embedded-AS-fronted MCP server) with authServerConfig.cimd.enabled: true and an upstream OIDC provider (reproduced against Entra ID, but upstream provider is irrelevant).
  2. Connect from VS Code (tested: 1.133.0) using its MCP client, which presents client_id=https://vscode.dev/oauth/client-metadata.json.
  3. VS Code's document (fetched directly, confirmed reachable and well-formed):
    {
      "client_name": "Visual Studio Code",
      "grant_types": ["authorization_code", "refresh_token", "urn:ietf:params:oauth:grant-type:device_code"],
      "response_types": ["code"],
      "token_endpoint_auth_method": "none",
      "application_type": "native",
      "client_id": "https://vscode.dev/oauth/client-metadata.json",
      "client_uri": "https://vscode.dev/product",
      "redirect_uris": ["http://127.0.0.1:33418/", "https://vscode.dev/redirect"]
    }
  4. The /oauth/authorize request fails, and the browser is shown:
    {"error":"invalid_client","error_description":"Client authentication failed (e.g., unknown client, no client authentication included, or unsupported authentication method). The requested OAuth 2.0 Client does not exist."}
    Other MCP clients that don't declare device_code in their CIMD/DCR metadata (e.g. Cursor) authenticate successfully against the same server.

Root cause

pkg/authserver/server/registration/dcr.go hardcodes the grant-types allowlist shared by both DCR and CIMD validation:

var allowedGrantTypes = map[string]bool{
    "authorization_code": true,
    "refresh_token":      true,
}

validateGrantTypes rejects the entire client if any declared grant type isn't in this map. pkg/authserver/storage/cimd_decorator.go calls this same validator (registration.ValidatePublicGrantTypes) when resolving a CIMD document, so a document that declares an extra grant type the client doesn't intend to use for this flow still fails the whole resolution, surfacing as fosite.ErrInvalidClient at the authorize/token endpoints.

Separately, pkg/authserver/server/handlers/authorize.go's error path has no logging for this failure — kubectl logs shows nothing, making this hard to diagnose from the server side. (Worth a follow-up issue if not already tracked, pkg/authserver/server/handlers/token.go does log the analogous case.)

Suggested fix

For CIMD specifically, filter/ignore grant types the server doesn't recognize when constructing the fosite.Client, rather than rejecting the whole document — a client is free to declare general capabilities (device code, for other flows/products) that aren't relevant to the authorization_code+PKCE flow being used here. At minimum, log the specific validation failure reason server-side so this doesn't present as an opaque "client does not exist."

Environment

  • ToolHive, tag v0.42.1
  • VS Code 1.133.0

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions