Skip to content

Commit a591757

Browse files
committed
test(auth): align OAuth metadata expectations with canonical URLs
Update docs, stories, and tests that asserted trailing slashes on root issuer and authorization_server metadata fields after the routes.py fix.
1 parent 77d36d8 commit a591757

10 files changed

Lines changed: 11 additions & 13 deletions

File tree

docs_src/identity_assertion/tutorial001.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ async def fetch_id_jag(audience: str, resource: str) -> str:
5555
storage=InMemoryTokenStorage(),
5656
client_id="finance-agent",
5757
client_secret="finance-agent-secret",
58-
issuer="https://auth.example.com/",
58+
issuer="https://auth.example.com",
5959
assertion_provider=fetch_id_jag,
6060
scope="notes:read",
6161
)

docs_src/identity_assertion/tutorial002.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
from mcp.server.auth.routes import create_auth_routes
1919
from mcp.shared.auth import JWT_BEARER_GRANT_TYPE, OAuthClientInformationFull, OAuthToken
2020

21-
ISSUER = "https://auth.example.com/"
21+
ISSUER = "https://auth.example.com"
2222
MCP_SERVER = "http://localhost:8001/mcp"
2323
IDP_ISSUER = "https://idp.example.com"
2424
IDP_SIGNING_KEY = "the-enterprise-idp-signing-key"

examples/stories/_shared/auth.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
from urllib.parse import parse_qs, urlsplit
1212

1313
import httpx
14-
from pydantic import AnyHttpUrl
1514

1615
from mcp.server.auth.provider import (
1716
AccessToken,
@@ -164,8 +163,8 @@ def auth_settings(
164163
"""
165164
scopes = required_scopes or ["mcp"]
166165
return AuthSettings(
167-
issuer_url=AnyHttpUrl(BASE_URL),
168-
resource_server_url=AnyHttpUrl(MCP_URL),
166+
issuer_url=BASE_URL, # type: ignore[arg-type]
167+
resource_server_url=MCP_URL, # type: ignore[arg-type]
169168
required_scopes=scopes,
170169
client_registration_options=ClientRegistrationOptions(enabled=True, valid_scopes=scopes, default_scopes=scopes),
171170
identity_assertion_enabled=identity_assertion_enabled,

examples/stories/identity_assertion/client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def build_auth(_http: httpx.AsyncClient) -> httpx.Auth:
3232
3333
`issuer` is configuration, not discovery: the provider fetches metadata from this issuer's
3434
well-known and never asks the MCP server which authorization server to use. The string must
35-
equal the `issuer` its metadata serves byte for byte (note the trailing slash).
35+
equal the `issuer` its metadata serves byte for byte.
3636
`Client(url, auth=...)` doesn't exist yet, so the harness threads this onto the underlying
3737
`httpx.AsyncClient` and hands `main` a target that is already routed through it.
3838
"""

examples/stories/identity_assertion/server.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@
2323
DEMO_CLIENT_SECRET = "demo-finance-agent-secret"
2424
DEMO_SCOPE = "mcp"
2525
# The exact `issuer` string this authorization server's metadata serves. The client must configure
26-
# the byte-identical string: RFC 8414 issuer comparison is character for character, and the
27-
# settings' `AnyHttpUrl` renders the path-less loopback origin with a trailing slash.
26+
# the byte-identical string: RFC 8414 issuer comparison is character for character.
2827
ISSUER = str(auth_settings().issuer_url)
2928

3029

examples/stories/oauth_client_credentials/server.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ def whoami() -> Whoami:
4848
@mcp.custom_route("/.well-known/oauth-authorization-server", methods=["GET"])
4949
async def as_metadata(request: Request) -> JSONResponse:
5050
meta = OAuthMetadata(
51-
issuer=AnyHttpUrl(BASE_URL),
51+
issuer=BASE_URL, # type: ignore[arg-type]
5252
authorization_endpoint=AnyHttpUrl(f"{BASE_URL}/authorize"), # unused; required
5353
token_endpoint=AnyHttpUrl(f"{BASE_URL}/token"),
5454
grant_types_supported=["client_credentials"],

examples/stories/oauth_client_credentials/server_lowlevel.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ async def call_tool(ctx: ServerRequestContext[Any], params: types.CallToolReques
4646

4747
async def as_metadata(request: Request) -> JSONResponse:
4848
meta = OAuthMetadata(
49-
issuer=AnyHttpUrl(BASE_URL),
49+
issuer=BASE_URL, # type: ignore[arg-type]
5050
authorization_endpoint=AnyHttpUrl(f"{BASE_URL}/authorize"), # unused; required
5151
token_endpoint=AnyHttpUrl(f"{BASE_URL}/token"),
5252
grant_types_supported=["client_credentials"],

tests/docs_src/test_authorization.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ async def test_the_metadata_document_is_built_from_auth_settings() -> None:
4747
assert response.json() == snapshot(
4848
{
4949
"resource": "http://127.0.0.1:8000/mcp",
50-
"authorization_servers": ["https://auth.example.com/"],
50+
"authorization_servers": ["https://auth.example.com"],
5151
"scopes_supported": ["notes:read"],
5252
"bearer_methods_supported": ["header"],
5353
}

tests/docs_src/test_identity_assertion.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ async def test_the_metadata_advertises_the_grant_type_and_the_id_jag_profile() -
137137
response = await http_client.get("/.well-known/oauth-authorization-server")
138138
assert response.status_code == 200
139139
metadata = response.json()
140-
assert metadata["issuer"] == "https://auth.example.com/"
140+
assert metadata["issuer"] == "https://auth.example.com"
141141
assert "urn:ietf:params:oauth:grant-type:jwt-bearer" in metadata["grant_types_supported"]
142142
assert metadata["authorization_grant_profiles_supported"] == ["urn:ietf:params:oauth:grant-profile:id-jag"]
143143

tests/server/mcpserver/auth/test_auth_integration.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ async def test_metadata_endpoint(self, test_client: httpx.AsyncClient):
317317
assert response.status_code == 200
318318

319319
metadata = response.json()
320-
assert metadata["issuer"] == "https://auth.example.com/"
320+
assert metadata["issuer"] == "https://auth.example.com"
321321
assert metadata["authorization_endpoint"] == "https://auth.example.com/authorize"
322322
assert metadata["token_endpoint"] == "https://auth.example.com/token"
323323
assert metadata["registration_endpoint"] == "https://auth.example.com/register"

0 commit comments

Comments
 (0)