Validate the iss authorization-response parameter (RFC 9207 / SEP-2468) (#2921)
This commit is contained in:
parent
b7a5bffed0
commit
48cf4950dc
3 changed files with 335 additions and 103 deletions
15
.github/actions/conformance/client.py
vendored
15
.github/actions/conformance/client.py
vendored
|
|
@ -43,7 +43,7 @@ from mcp.client.auth.extensions.client_credentials import (
|
|||
)
|
||||
from mcp.client.context import ClientRequestContext
|
||||
from mcp.client.streamable_http import streamable_http_client
|
||||
from mcp.shared.auth import OAuthClientInformationFull, OAuthClientMetadata, OAuthToken
|
||||
from mcp.shared.auth import AuthorizationCodeResult, OAuthClientInformationFull, OAuthClientMetadata, OAuthToken
|
||||
|
||||
# Set up logging to stderr (stdout is for conformance test output)
|
||||
logging.basicConfig(
|
||||
|
|
@ -119,6 +119,7 @@ class ConformanceOAuthCallbackHandler:
|
|||
def __init__(self) -> None:
|
||||
self._auth_code: str | None = None
|
||||
self._state: str | None = None
|
||||
self._iss: str | None = None
|
||||
|
||||
async def handle_redirect(self, authorization_url: str) -> None:
|
||||
"""Fetch the authorization URL and extract the auth code from the redirect."""
|
||||
|
|
@ -140,6 +141,8 @@ class ConformanceOAuthCallbackHandler:
|
|||
self._auth_code = query_params["code"][0]
|
||||
state_values = query_params.get("state")
|
||||
self._state = state_values[0] if state_values else None
|
||||
iss_values = query_params.get("iss")
|
||||
self._iss = iss_values[0] if iss_values else None
|
||||
logger.debug(f"Got auth code from redirect: {self._auth_code[:10]}...")
|
||||
return
|
||||
else:
|
||||
|
|
@ -149,15 +152,15 @@ class ConformanceOAuthCallbackHandler:
|
|||
else:
|
||||
raise RuntimeError(f"Expected redirect response, got {response.status_code} from {authorization_url}")
|
||||
|
||||
async def handle_callback(self) -> tuple[str, str | None]:
|
||||
"""Return the captured auth code and state."""
|
||||
async def handle_callback(self) -> AuthorizationCodeResult:
|
||||
"""Return the captured auth code, state, and iss."""
|
||||
if self._auth_code is None:
|
||||
raise RuntimeError("No authorization code available - was handle_redirect called?")
|
||||
auth_code = self._auth_code
|
||||
state = self._state
|
||||
result = AuthorizationCodeResult(code=self._auth_code, state=self._state, iss=self._iss)
|
||||
self._auth_code = None
|
||||
self._state = None
|
||||
return auth_code, state
|
||||
self._iss = None
|
||||
return result
|
||||
|
||||
|
||||
# --- Scenario Handlers ---
|
||||
|
|
|
|||
|
|
@ -44,6 +44,15 @@ client:
|
|||
- auth/token-endpoint-auth-post
|
||||
- auth/token-endpoint-auth-none
|
||||
- auth/offline-access-not-supported
|
||||
# SEP-2468 (authorization response iss parameter) is implemented, but these
|
||||
# 2026-introduced scenarios reach DCR and so still fail the application_type
|
||||
# check above; they unblock with SEP-837, not SEP-2468.
|
||||
- auth/iss-supported
|
||||
- auth/iss-not-advertised
|
||||
- auth/iss-supported-missing
|
||||
- auth/iss-wrong-issuer
|
||||
- auth/iss-unexpected
|
||||
- auth/iss-normalized
|
||||
|
||||
# --- Auth scenarios cut short by the 2026 connection lifecycle ---
|
||||
# The auth fixture flow drives the 2025 stateful lifecycle; the 2026-mode
|
||||
|
|
@ -65,14 +74,6 @@ client:
|
|||
- http-invalid-tool-headers
|
||||
# SEP-2106 (JSON Schema $ref handling): client still dereferences network $refs.
|
||||
- json-schema-ref-no-deref
|
||||
# SEP-2468 (authorization response iss parameter): not implemented in the client.
|
||||
- auth/iss-supported
|
||||
- auth/iss-not-advertised
|
||||
- auth/iss-supported-missing
|
||||
- auth/iss-wrong-issuer
|
||||
- auth/iss-unexpected
|
||||
- auth/iss-normalized
|
||||
- auth/metadata-issuer-mismatch
|
||||
# SEP-2352 (authorization server migration): client does not re-register when
|
||||
# PRM authorization_servers changes.
|
||||
- auth/authorization-server-migration
|
||||
|
|
|
|||
|
|
@ -24,20 +24,21 @@ client:
|
|||
- http-invalid-tool-headers
|
||||
# SEP-2106 (JSON Schema $ref handling): client still dereferences network $refs.
|
||||
- json-schema-ref-no-deref
|
||||
# SEP-2468 (authorization response iss parameter): not implemented in the client.
|
||||
# SEP-2352 (authorization server migration): client does not re-register when
|
||||
# PRM authorization_servers changes.
|
||||
- auth/authorization-server-migration
|
||||
# SEP-837 (application_type during DCR): the check fires on every non-legacy
|
||||
# spec version (the default LATEST is 2026-07-28). The client omits
|
||||
# application_type during Dynamic Client Registration, so every scenario that
|
||||
# reaches DCR fails it. SEP-2468 iss validation is implemented, so these now
|
||||
# fail only on the application_type check, not on iss.
|
||||
- auth/offline-access-not-supported
|
||||
- auth/iss-supported
|
||||
- auth/iss-not-advertised
|
||||
- auth/iss-supported-missing
|
||||
- auth/iss-wrong-issuer
|
||||
- auth/iss-unexpected
|
||||
- auth/iss-normalized
|
||||
- auth/metadata-issuer-mismatch
|
||||
# SEP-2352 (authorization server migration): client does not re-register when
|
||||
# PRM authorization_servers changes.
|
||||
- auth/authorization-server-migration
|
||||
# SEP-837 (application_type during DCR): the check only fires on draft-version
|
||||
# runs; this draft scenario is the one place the client still hits it.
|
||||
- auth/offline-access-not-supported
|
||||
|
||||
# --- Pre-existing scenarios that fail on checks added after conformance 0.1.15 ---
|
||||
# SEP-2350 (scope step-up): WARNING-only; the expected-failures evaluator
|
||||
|
|
|
|||
Loading…
Reference in a new issue