Skip to content

Commit 1f53180

Browse files
committed
test: add validate_scope unit tests for None scope handling
Add regression tests for #2216 verifying that validate_scope() correctly allows any requested scopes when the client has no scope restrictions (self.scope is None).
1 parent 15f480a commit 1f53180

File tree

1 file changed

+53
-1
lines changed

1 file changed

+53
-1
lines changed

tests/shared/test_auth.py

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
"""Tests for OAuth 2.0 shared code."""
22

3-
from mcp.shared.auth import OAuthMetadata
3+
import pytest
4+
from pydantic import AnyUrl
5+
6+
from mcp.shared.auth import InvalidScopeError, OAuthClientMetadata, OAuthMetadata
47

58

69
def test_oauth():
@@ -58,3 +61,52 @@ def test_oauth_with_jarm():
5861
"token_endpoint_auth_methods_supported": ["client_secret_basic", "client_secret_post"],
5962
}
6063
)
64+
65+
66+
class TestValidateScope:
67+
"""Tests for OAuthClientMetadata.validate_scope()."""
68+
69+
def _make_client(self, scope=None):
70+
return OAuthClientMetadata(
71+
redirect_uris=[AnyUrl("http://localhost:3000/callback")],
72+
scope=scope,
73+
)
74+
75+
def test_requested_none_returns_none(self):
76+
"""When no scope is requested, validate_scope returns None."""
77+
client = self._make_client(scope="read write")
78+
assert client.validate_scope(None) is None
79+
80+
def test_client_scope_none_allows_any_requested_scopes(self):
81+
"""When client has no scope restrictions (None), any requested scopes are allowed.
82+
83+
Regression test for #2216: validate_scope treated None as empty list,
84+
rejecting all scopes with InvalidScopeError.
85+
"""
86+
client = self._make_client(scope=None)
87+
result = client.validate_scope("read write admin")
88+
assert result == ["read", "write", "admin"]
89+
90+
def test_client_scope_none_allows_single_scope(self):
91+
"""When client has no scope restrictions, a single requested scope is allowed."""
92+
client = self._make_client(scope=None)
93+
result = client.validate_scope("read")
94+
assert result == ["read"]
95+
96+
def test_allowed_scopes_accepted(self):
97+
"""Requested scopes that are a subset of client scopes are accepted."""
98+
client = self._make_client(scope="read write admin")
99+
result = client.validate_scope("read write")
100+
assert result == ["read", "write"]
101+
102+
def test_disallowed_scope_raises(self):
103+
"""Requesting a scope not in the client's registered scopes raises InvalidScopeError."""
104+
client = self._make_client(scope="read write")
105+
with pytest.raises(InvalidScopeError, match="admin"):
106+
client.validate_scope("read admin")
107+
108+
def test_all_scopes_match(self):
109+
"""Requesting exactly the registered scopes works."""
110+
client = self._make_client(scope="read write")
111+
result = client.validate_scope("read write")
112+
assert result == ["read", "write"]

0 commit comments

Comments
 (0)