github / github/copilot-cli

MCP OAuth authorize request omits 'scope' parameter for Entra ID servers with static oauthClientId, causing AADSTS900144

Đang mở
#4,582 2 bình luận 0 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

triage
Ngôn ngữ chính
Shell
Star
11.2k
Fork
1.9k
Merge trung bình
14 giờ 16 phút
Pull request đã merge (30 ngày)
6

Mô tả

Describe the bug

When signing in to a remote (type: http) MCP server whose authorization server is Microsoft Entra ID, configured with a statically-provided oauthClientId + oauthPublicClient: true (no Dynamic Client Registration), Copilot CLI opens the browser to Entra ID's /authorize endpoint without a scope query parameter at all, even though the server's OAuth metadata correctly advertises scopes_supported. Microsoft Entra ID's v2.0 endpoint requires scope on both the authorization request and the token exchange (unlike base RFC 6749, where it's optional), so the flow fails immediately with:

Sorry, but we're having trouble signing you in.

AADSTS900144: The request body must contain the following parameter: 'scope'.

This is very likely the same root-cause bug class as #4464 (silent refresh fails with AADSTS70011 due to mishandled scope on the refresh_token grant) — in both cases the OAuth client isn't correctly deriving/propagating the scope parameter for Entra ID flows built from server-advertised metadata. It's also functionally identical to anthropics/claude-code#69547, which reports the exact same AADSTS900144 error for the exact same scenario (pre-registered/static public client against an Entra ID-backed MCP server, since Entra ID doesn't support DCR) in a different MCP client, suggesting this is a well-known interoperability gap for MCP clients talking to Entra ID with a fixed client id.

Affected version

1.0.80 (Windows x64). Also reproduced on a locally-modified 1.0.79-era build before upgrading.

Steps to reproduce the behavior
  1. Configure a remote HTTP MCP server backed by Microsoft Entra ID with a statically-provided client id (no DCR), e.g. in ~/.copilot/mcp-config.json:
  {
     "mcpServers": {
       "example-server": {
         "type": "http",
         "url": "https://example.org",
         "oauthClientId": "<entra-app-client-id>",
         "oauthPublicClient": true
       }
     }
   }

The server's /.well-known/oauth-protected-resource and /.well-known/oauth-authorization-server documents are RFC 8414-compliant: authorization_servers matches the document's own issuer exactly, and authorization_endpoint/token_endpoint point at the real Microsoft Entra ID tenant endpoints (https://login.microsoftonline.com/<tenant>/oauth2/v2.0/authorize and .../token). The authorization-server metadata's scopes_supported correctly lists the resource's App ID URI scope, e.g. ["openid", "profile", "email", "api://<app-id>/access_as_user"].
2. In the app, open MCP settings and click Sign in for that server.
3. A browser window opens and navigates to Microsoft's /authorize endpoint. The observed request URL was:

  https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/authorize
     ?response_type=code
     &client_id=<client-id>
     &state=<state>
     &code_challenge=<challenge>
     &code_challenge_method=S256
     &redirect_uri=http%3A%2F%2F127.0.0.1%3A<port>%2F
     &client_session=<session-id>

Note there is no scope= parameter anywhere in this URL.
4. Entra ID immediately rejects the request:

   AADSTS900144: The request body must contain the following parameter: 'scope'.
Expected behavior

The MCP OAuth client should build the scope parameter for the /authorize request (and again for the /token exchange) from the target server's advertised scopes_supported (from either the oauth-authorization-server or oauth-protected-resource metadata document), the same way it presumably does for servers that use Dynamic Client Registration. For Entra ID specifically, scope must be present on every leg of the flow (authorize request, token exchange, and refresh), since Entra ID's v2.0 endpoint treats scope as mandatory rather than optional.

Additional context
  • The corresponding server-side OAuth metadata was independently verified as fully RFC 8414 §3.3-compliant via repeated direct HTTP requests (issuer exactly matches authorization_servers, byte-for-byte, across 15 parallel requests) before this bug surfaced, ruling out a server-side metadata problem.
  • This may be related to how the client resolves scope when a server config supplies a static oauthClientId/oauthPublicClient: true and skips the registration_endpoint (Dynamic Client Registration) flow — DCR responses may carry scope information that the static-client path doesn't otherwise obtain from scopes_supported.
  • Related issues in this repo: #4464 (refresh-token grant mishandles Entra ID scope, AADSTS70011), #4439 / #4480 (separate RFC 8414 issuer-mismatch bugs, now fixed/in progress).
  • Related issue in a different MCP client with an identical error and scenario: anthropics/claude-code#69547.

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Hướng nghiên cứu

Bắt đầu với luồng Sign in trong cài đặt MCP dành cho một máy chủ HTTP từ xa được cấu hình trong ~/.copilot/mcp-config.json, sau đó theo dõi cách siêu dữ liệu oauth-authorization-server và oauth-protected-resource được sử dụng cùng với một oauthClientId tĩnh. Tái hiện với Entra ID và xác minh rằng scope được truyền qua quá trình ủy quyền, trao đổi token và làm mới, sử dụng issue #4464 làm ngữ cảnh liên quan.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Đánh giá

Công nghệ
azure
Lĩnh vực
api, authentication
Loại issue
Lỗi
Độ khó
4/5
Thời gian dự kiến
3-5 ngày
Mức độ hoạt động
Sôi nổi
Độ rõ ràng
Khá rõ ràng
Mức phù hợp với người mới
55/100

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.