Require integrity protection for MRTR requestState (#3032)

This commit is contained in:
Max 2026-06-30 21:30:32 +01:00 • committed by GitHub
commit 7322ca56f4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 3338 additions and 183 deletions

View file

@ -9,8 +9,18 @@ from starlette.datastructures import Headers
from starlette.requests import Request
from starlette.types import Message, Receive, Scope, Send
from mcp.server.auth.middleware.bearer_auth import AuthenticatedUser, BearerAuthBackend, RequireAuthMiddleware
from mcp.server.auth.provider import AccessToken, OAuthAuthorizationServerProvider, ProviderTokenVerifier
from mcp.server.auth.middleware.bearer_auth import (
AuthenticatedUser,
BearerAuthBackend,
RequireAuthMiddleware,
authorization_context,
)
from mcp.server.auth.provider import (
AccessToken,
OAuthAuthorizationServerProvider,
ProviderTokenVerifier,
principal_components,
)
class MockOAuthProvider:
@ -446,3 +456,16 @@ class TestRequireAuthMiddleware:
assert app.scope == scope
assert app.receive == receive
assert app.send == send
def test_authorization_context_is_built_from_principal_components() -> None:
"""Session ownership identifies the principal via the shared principal_components triple."""
token = AccessToken(
token="t", client_id="client-1", scopes=[], subject="alice", claims={"iss": "https://as.example"}
)
client_id, issuer, subject = principal_components(token)
assert authorization_context(AuthenticatedUser(token)) == {
"client_id": client_id,
"issuer": issuer,
"subject": subject,
}

View file

@ -1,6 +1,6 @@
"""Tests for mcp.server.auth.provider module."""
from mcp.server.auth.provider import construct_redirect_uri
from mcp.server.auth.provider import AccessToken, construct_redirect_uri, principal_components
def test_construct_redirect_uri_no_existing_params():
@ -77,3 +77,14 @@ def test_construct_redirect_uri_encoded_values():
# urlencode uses + for spaces by default
assert "state=test+state+with+spaces" in result
def test_principal_components_composes_client_issuer_subject():
"""The triple identifying a token's principal, degrading per missing component."""
bare = AccessToken(token="t", client_id="client-1", scopes=[])
assert principal_components(bare) == ("client-1", None, None)
full = AccessToken(
token="t", client_id="client-1", scopes=[], subject="alice", claims={"iss": "https://as.example"}
)
assert principal_components(full) == ("client-1", "https://as.example", "alice")