Hacktoberfest 2026:維護者為十月標記出來的 issue,仍然開放、適合新手。 瀏覽 Hacktoberfest issue

OAuth redirect URI port mismatch breaks login to most MCP servers

未關閉
#4,968 0 則留言 0 個 reaction 已指派 0 人 在 GitHub 檢視

維護者通常 1 天內回覆

還沒有人認領這個 Issue。

評估

難度
4/5
預估耗時
3-5 天
新手友好度
52/100
Issue 類型
缺陷
描述清晰度
基本清楚
活躍度
活躍
技術堆疊
node.js

研究方向

Start with the /mcp add OAuth flow and inspect the published client-metadata.json alongside the loopback listener in the shipped SEA binary. Compare the advertised redirect URI with the runtime redirect_uri, then verify the chosen behavior against a strict-matching MCP OAuth server and the RFC 8252 loopback requirement.

由索引模型根據 Issue 內容生成。

描述

triage

OAuth redirect URI port mismatch breaks login to most MCP servers

Summary

copilot CLI publishes a CIMD (Client ID Metadata Document) that declares a
single loopback redirect URI on a fixed port, but at runtime the CLI binds an
ephemeral loopback port and sends that port in the OAuth redirect_uri
parameter. GitHub's own OAuth server accepts the mismatch (per RFC 8252 §7.3
loopback matching), but many third-party OAuth servers — including
Entra/Azure-fronted MCP servers — do strict string matching against the
registered redirect_uris and reject the request.

The result is that authentication fails against almost every non-GitHub MCP
server
users try to connect. Claude Code and Codex CLI are not affected in
the same environments.

Environment

  • CLI version: GitHub Copilot CLI 1.0.88
  • OS: macOS (arm64)
  • Install: Homebrew cask copilot-cli (SEA binary)

Reproducer

  1. Configure any MCP server whose OAuth authorize endpoint validates
    redirect_uri by exact match against the CIMD's redirect_uris list.
    (Entra/Azure-fronted services typically behave this way.)
  2. Trigger the OAuth flow from Copilot CLI:
    /mcp add <server-url> (or however the server is registered), then log in.
  3. The browser lands on the authorize endpoint, which returns:
{
  "error": "invalid_request",
  "error_description": "Redirect URI 'http://127.0.0.1:52752/' does not match CIMD redirect_uris.",
  "state": "..."
}

The port (52752 above) changes on every attempt.

Expected behavior

The redirect_uri sent to the authorize endpoint should either:

  • (a) match the port published in the CIMD, i.e. http://127.0.0.1:33418/, so
    strict-matching servers accept it; or
  • (b) rely on RFC 8252 §7.3 loopback matching and have the CIMD advertise
    http://127.0.0.1/ (no port), making clear to server implementers that
    port-agnostic matching is expected.

Today it does neither: it publishes a specific port and then uses a different
one.

Actual behavior / root cause

The CLI's published metadata at
https://github.com/copilot/cli/client-metadata.json:

{
  "client_id": "https://github.com/copilot/cli/client-metadata.json",
  "client_name": "GitHub Copilot CLI",
  "application_type": "native",
  "redirect_uris": ["http://127.0.0.1:33418/"],
  ...
}

But the CLI's OAuth loopback listener is bound with port 0 (verifiable by
inspecting the SEA blob inside the shipped binary):

// Port 0 = let the OS pick a free ephemeral port. Bind to loopback only.
await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
const address = server.address();
const port = typeof address === "object" && address ? address.port : 0;

The dynamically-assigned port then flows into the OAuth redirect_uri, which
never equals 33418.

Impact

  • Blocks Copilot CLI from authenticating against most third-party MCP servers,
    which is a large and growing set as MCP adoption widens.
  • Internal reports at multiple organisations indicate the same failure pattern
    across every non-GitHub MCP they've tried, with Claude Code / Codex CLI
    unaffected in the same environments.
  • Users have no clean local workaround. The one lever we found —
    COPILOT_MCP_CIMD_CLIENT_ID_URL overriding the CIMD document URL — requires
    self-hosting a metadata file that enumerates every ephemeral loopback port,
    which is fragile and requires the MCP server to dynamically trust arbitrary
    CIMDs.

Suggested fixes (either is sufficient)

  1. Bind the published port. Change the listener to
    server.listen(33418, "127.0.0.1", …) with a fallback strategy (retry with
    an ephemeral port only if 33418 is in use, and clearly document the
    fallback), so the common case matches the CIMD exactly.
  2. Publish port-agnostic CIMD. Change redirect_uris in
    client-metadata.json to ["http://127.0.0.1/"] and rely on the RFC 8252
    §7.3 loopback rule. This shifts the responsibility to non-conformant OAuth
    servers, which is arguably correct, but will not fix real-world usage until
    those servers are updated.

Option 1 is the most defensive; option 2 is the most spec-pure. A combination
(bind 33418 first, publish 127.0.0.1/) would maximise interoperability.

References

  • RFC 8252 §7.3 (Loopback Interface Redirection): loopback redirects SHOULD be
    matched ignoring the port component.
  • OAuth 2.0 for Native Apps client identity metadata document (CIMD) spec.

Drafted with GitHub Copilot CLI.

主要語言
Shell
星號
11.2k
分支
1.9k
平均合併
17 小時 6 分鐘
30 天內合併 PR
5

環境準備

從這裡開始

  1. 先讀完整個 Issue,再讀專案的貢獻指南。
  2. 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
  3. Fork 儲存庫,在一個分支上完成修改。
  4. 送出 Pull Request,並在描述裡引用這個 Issue 編號。

github/copilot-cli 的其他 Issue

查看 github/copilot-cli 的全部 Issue

相似的 Issue

更多 Shell/Bash Issue

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。