Skip to content

Commit 579a6be

Browse files
Include client_id in client_credentials token request body
ClientCredentialsOAuthProvider._exchange_token_client_credentials() was missing client_id in the token_data dict. Per RFC 6749 Section 2.3.1, when using client_secret_post authentication, both client_id and client_secret must be in the request body. The prepare_token_auth() method only adds client_secret, so client_id was never sent. This caused authentication failures when using client_secret_post with OAuth providers that require client_id in the body. Fixes #2128 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 528abfa commit 579a6be

2 files changed

Lines changed: 3 additions & 0 deletions

File tree

src/mcp/client/auth/extensions/client_credentials.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ async def _exchange_token_client_credentials(self) -> httpx.Request:
9090
"""Build token exchange request for client_credentials grant."""
9191
token_data: dict[str, Any] = {
9292
"grant_type": "client_credentials",
93+
"client_id": self._fixed_client_info.client_id,
9394
}
9495

9596
headers: dict[str, str] = {"Content-Type": "application/x-www-form-urlencoded"}

tests/client/auth/extensions/test_client_credentials.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ async def test_exchange_token_client_credentials(self, mock_storage: MockTokenSt
249249

250250
content = urllib.parse.unquote_plus(request.content.decode())
251251
assert "grant_type=client_credentials" in content
252+
assert "client_id=test-client-id" in content
252253
assert "scope=read write" in content
253254
assert "resource=https://api.example.com/v1/mcp" in content
254255

@@ -272,6 +273,7 @@ async def test_exchange_token_without_scopes(self, mock_storage: MockTokenStorag
272273

273274
content = urllib.parse.unquote_plus(request.content.decode())
274275
assert "grant_type=client_credentials" in content
276+
assert "client_id=test-client-id" in content
275277
assert "scope=" not in content
276278
assert "resource=" not in content
277279

0 commit comments

Comments
 (0)