Skip to content

[BUG]: OAuth token refresh fails with invalid redirect_uri when using enterprise MCP servers #1491

@christso

Description

@christso

Describe the bug

Copilot CLI fails OAuth token refresh with invalid redirect_uri error when using enterprise MCP servers that require fixed callback ports.

Context

Many enterprise OAuth servers (like Keycloak) enforce strict redirect URI validation that requires exact URI matches, including port numbers.

Copilot CLI uses random ephemeral ports for its OAuth callback server:

  • Initial authentication works (the random port gets registered with the OAuth server)
  • Token refresh fails because Copilot CLI spawns a callback server on a different random port
  • The new port doesn't match the registered redirect URI
  • OAuth server rejects with invalid redirect_uri
Image

Why This Breaks Enterprise Deployments

Enterprise OAuth servers (like Keycloak with "Trusted Hosts" policy) often:

  • Block Dynamic Client Registration from untrusted hosts
  • Require redirect URIs to be explicitly pre-registered
  • Validate redirect URIs with exact matching (including port)

Result: Users must re-authenticate via browser on every token expiration instead of automatic token refresh.

Affected version

0.0.410

Steps to reproduce the behavior

Prerequisites

  • Enterprise MCP server with OAuth authentication (e.g., Keycloak)
  • OAuth server configured with strict redirect URI validation (exact match required)
  • Dynamic Client Registration disabled or restricted by "Trusted Hosts" policy

Steps

  1. Initial authentication
  2. Copilot CLI spawns callback server on random port (e.g., http://127.0.0.1:55167/callback
  3. Browser opens, user completes OAuth login
  4. Server registers the redirect URI with that specific port
  5. Tokens are stored successfully
  6. Wait for token expiration (typically 24 hours, or force expiration by manually editing ~/.copilot/mcp-oauth-config/.json to set a past expiresAt)
  7. Copilot CLI detects expired token
  8. Attempts token refresh by spawning callback server on a different random port (e.g., http://127.0.0.1:48923/callback)
  9. OAuth server rejects the request with invalid redirect_uri error

Expected behavior

Token refresh should succeed using the same callback port that was registered during initial authentication.

Implementation Options

  1. Fixed default port (like OpenCode uses port 19876)
  2. Configurable port via CLI flag or config file (like Codex's mcp_oauth_callback_port)
  3. Preferred port with fallback (like VS Code uses port 33418, falls back to random if unavailable)

Recommended Approach

Use VS Code's hybrid strategy (option 3):

  • Try a default port (e.g., 33418 or 19876)
  • Fall back to ephemeral port only if the default port is unavailable
  • This balances enterprise compatibility with single-machine multi-instance scenarios

Comparison with Other Tools

Tool Port Strategy Enterprise Compatible?
Copilot CLI (current) Random ephemeral ❌ No (breaks on refresh)
VS Code Preferred 33418, fallback random ✅ Yes
OpenCode Fixed 19876 ✅ Yes
Claude Code Fixed 41842 ✅ Yes
Codex Ephemeral (configurable) ✅ Yes

Configuration Example

{
  "mcpServers": {
    "enterprise-mcp": {
      "type": "http",
      "url": "https://mcp.example.com",
      "oauth": {
        "callbackPort": 55167
      },
      "tools": ["*"]
    }
  }
}

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions