Skip to content

Commit 5e7a0bf

Browse files
committed
Add tests for /revoke validation
1 parent 6768efb commit 5e7a0bf

File tree

2 files changed

+39
-1
lines changed

2 files changed

+39
-1
lines changed

src/mcp/server/auth/handlers/revoke.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
Corresponds to TypeScript file: src/server/auth/handlers/revoke.ts
55
"""
66

7+
from tokenize import Token
78
from typing import Callable
89

910
from pydantic import ValidationError
@@ -12,12 +13,15 @@
1213

1314
from mcp.server.auth.errors import (
1415
InvalidRequestError,
16+
stringify_pydantic_error,
1517
)
1618
from mcp.server.auth.middleware.client_auth import (
1719
ClientAuthenticator,
1820
ClientAuthRequest,
1921
)
2022
from mcp.server.auth.provider import OAuthServerProvider, OAuthTokenRevocationRequest
23+
from mcp.server.auth.json_response import PydanticJSONResponse
24+
from mcp.shared.auth import TokenErrorResponse
2125

2226

2327
class RevocationRequest(OAuthTokenRevocationRequest, ClientAuthRequest):
@@ -35,7 +39,10 @@ async def revocation_handler(request: Request) -> Response:
3539
form_data = await request.form()
3640
revocation_request = RevocationRequest.model_validate(dict(form_data))
3741
except ValidationError as e:
38-
raise InvalidRequestError(f"Invalid request body: {e}")
42+
return PydanticJSONResponse(status_code=400,content=TokenErrorResponse(
43+
error="invalid_request",
44+
error_description=stringify_pydantic_error(e)
45+
))
3946

4047
# Authenticate client
4148
client_auth_result = await client_authenticator(revocation_request)

tests/server/fastmcp/auth/test_auth_integration.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -887,6 +887,37 @@ async def test_authorization_get(
887887
assert await mock_oauth_provider.load_access_token(
888888
new_token_response["access_token"]
889889
) is None
890+
@pytest.mark.anyio
891+
async def test_revoke_invalid_token(self, test_client, registered_client):
892+
"""Test revoking an invalid token."""
893+
response = await test_client.post(
894+
"/revoke",
895+
data={
896+
"client_id": registered_client["client_id"],
897+
"client_secret": registered_client["client_secret"],
898+
"token": "invalid_token",
899+
},
900+
)
901+
# per RFC, this should return 200 even if the token is invalid
902+
assert response.status_code == 200
903+
@pytest.mark.anyio
904+
async def test_revoke_with_malformed_token(self, test_client, registered_client):
905+
response = await test_client.post(
906+
"/revoke",
907+
data={
908+
"client_id": registered_client["client_id"],
909+
"client_secret": registered_client["client_secret"],
910+
"token": 123,
911+
"token_type_hint": "asdf"
912+
},
913+
)
914+
assert response.status_code == 400
915+
error_response = response.json()
916+
assert error_response["error"] == "invalid_request"
917+
assert "token_type_hint" in error_response["error_description"]
918+
919+
920+
890921

891922

892923
class TestFastMCPWithAuth:

0 commit comments

Comments
 (0)