mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-09 07:09:11 +02:00
Bind CIMD assertion audience to the advertised token endpoint (#4659)
A bare-authority base_url renders with a trailing slash, so the expected aud was https://host//token while the metadata advertised https://host/token.
This commit is contained in:
parent
6c4ba6b420
commit
0c1c42f151
2 changed files with 50 additions and 1 deletions
|
|
@ -10,6 +10,7 @@ from key_value.aio.stores.memory import MemoryStore
|
|||
from mcp.shared.auth import OAuthClientInformationFull
|
||||
from pydantic import AnyUrl
|
||||
from starlette.applications import Starlette
|
||||
from starlette.testclient import TestClient
|
||||
|
||||
from fastmcp.server.auth.oauth_proxy import OAuthProxy
|
||||
from fastmcp.server.auth.oauth_proxy.models import OAuthTransaction
|
||||
|
|
@ -618,3 +619,38 @@ class TestIdpCallbackSuccessForwarding:
|
|||
# byte-for-byte.
|
||||
assert "flag" in query
|
||||
assert "sig=%FF%FE" in query
|
||||
|
||||
|
||||
class TestCIMDTokenEndpointAudience:
|
||||
"""The `aud` expected on a CIMD assertion matches the advertised token endpoint."""
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"base_url",
|
||||
["https://api.example.com", "https://api.example.com/api"],
|
||||
)
|
||||
def test_token_endpoint_url_matches_advertised_metadata(
|
||||
self, jwt_verifier, base_url: str
|
||||
):
|
||||
"""A bare-authority base_url must not expect `aud` of `https://host//token`.
|
||||
|
||||
CIMD is enabled by default, and a spec-following client binds its
|
||||
private_key_jwt assertion to the `token_endpoint` the metadata
|
||||
advertises. If the proxy expects a different string, every such client
|
||||
is rejected with invalid_client.
|
||||
"""
|
||||
proxy = OAuthProxy(
|
||||
upstream_authorization_endpoint="https://auth.example.com/authorize",
|
||||
upstream_token_endpoint="https://auth.example.com/token",
|
||||
upstream_client_id="client-123",
|
||||
upstream_client_secret="secret-456",
|
||||
token_verifier=jwt_verifier,
|
||||
base_url=base_url,
|
||||
jwt_signing_key="test-secret",
|
||||
client_storage=MemoryStore(),
|
||||
)
|
||||
|
||||
app = Starlette(routes=proxy.get_routes(mcp_path="/mcp"))
|
||||
with TestClient(app) as client:
|
||||
metadata = client.get("/.well-known/oauth-authorization-server").json()
|
||||
|
||||
assert proxy.token_endpoint_url == metadata["token_endpoint"]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue