49b9bb6724
Deploy Docs / deploy-docs (push) Failing after 1s
Conformance Tests / client-conformance (push) Failing after 3s
Conformance Tests / server-conformance (push) Failing after 1s
GitHub Actions Security Analysis / zizmor (push) Failing after 1s
CI / checks (push) Failing after 59m20s
CI / all-green (push) Waiting to run
91 lines
3.6 KiB
Python
91 lines
3.6 KiB
Python
"""Tests for mcp.server.auth.provider module."""
|
|
|
|
from mcp.server.auth.provider import AccessToken, construct_redirect_uri, principal_components
|
|
|
|
|
|
def test_construct_redirect_uri_no_existing_params():
|
|
"""Test construct_redirect_uri with no existing query parameters."""
|
|
base_uri = "http://localhost:8000/callback"
|
|
result = construct_redirect_uri(base_uri, code="auth_code", state="test_state")
|
|
|
|
assert "http://localhost:8000/callback?code=auth_code&state=test_state" == result
|
|
|
|
|
|
def test_construct_redirect_uri_with_existing_params():
|
|
"""Test construct_redirect_uri with existing query parameters (regression test for #1279)."""
|
|
base_uri = "http://localhost:8000/callback?session_id=1234"
|
|
result = construct_redirect_uri(base_uri, code="auth_code", state="test_state")
|
|
|
|
# Should preserve existing params and add new ones
|
|
assert "session_id=1234" in result
|
|
assert "code=auth_code" in result
|
|
assert "state=test_state" in result
|
|
assert result.startswith("http://localhost:8000/callback?")
|
|
|
|
|
|
def test_construct_redirect_uri_multiple_existing_params():
|
|
"""Test construct_redirect_uri with multiple existing query parameters."""
|
|
base_uri = "http://localhost:8000/callback?session_id=1234&user=test"
|
|
result = construct_redirect_uri(base_uri, code="auth_code")
|
|
|
|
assert "session_id=1234" in result
|
|
assert "user=test" in result
|
|
assert "code=auth_code" in result
|
|
|
|
|
|
def test_construct_redirect_uri_with_none_values():
|
|
"""Test construct_redirect_uri filters out None values."""
|
|
base_uri = "http://localhost:8000/callback"
|
|
result = construct_redirect_uri(base_uri, code="auth_code", state=None)
|
|
|
|
assert result == "http://localhost:8000/callback?code=auth_code"
|
|
assert "state" not in result
|
|
|
|
|
|
def test_construct_redirect_uri_empty_params():
|
|
"""Test construct_redirect_uri with no additional parameters."""
|
|
base_uri = "http://localhost:8000/callback?existing=param"
|
|
result = construct_redirect_uri(base_uri)
|
|
|
|
assert result == "http://localhost:8000/callback?existing=param"
|
|
|
|
|
|
def test_construct_redirect_uri_duplicate_param_names():
|
|
"""Test construct_redirect_uri when adding param that already exists."""
|
|
base_uri = "http://localhost:8000/callback?code=existing"
|
|
result = construct_redirect_uri(base_uri, code="new_code")
|
|
|
|
# Should contain both values (this is expected behavior of parse_qs/urlencode)
|
|
assert "code=existing" in result
|
|
assert "code=new_code" in result
|
|
|
|
|
|
def test_construct_redirect_uri_multivalued_existing_params():
|
|
"""Test construct_redirect_uri with existing multi-valued parameters."""
|
|
base_uri = "http://localhost:8000/callback?scope=read&scope=write"
|
|
result = construct_redirect_uri(base_uri, code="auth_code")
|
|
|
|
assert "scope=read" in result
|
|
assert "scope=write" in result
|
|
assert "code=auth_code" in result
|
|
|
|
|
|
def test_construct_redirect_uri_encoded_values():
|
|
"""Test construct_redirect_uri handles URL encoding properly."""
|
|
base_uri = "http://localhost:8000/callback"
|
|
result = construct_redirect_uri(base_uri, state="test state with spaces")
|
|
|
|
# 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")
|