Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions mcpauth/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,11 @@ class AuthServerType(str, Enum):
OIDC = "oidc"


class AuthorizationServerMetadataDefaults(Enum):
grant_types_supported = ["authorization_code", "implicit"]
response_modes_supported = ["query", "fragment"]


class AuthServerConfig(BaseModel):
"""
Configuration for the remote authorization server integrated with the MCP server.
Expand Down
10 changes: 6 additions & 4 deletions mcpauth/utils/_validate_server_config.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from enum import Enum
from typing import Any, Dict, List, Optional
from pydantic import BaseModel
from ..config import AuthServerConfig
from ..config import AuthServerConfig, AuthorizationServerMetadataDefaults


class AuthServerConfigErrorCode(str, Enum):
Expand Down Expand Up @@ -97,6 +97,7 @@ def validate_server_config(
invalid (`{ is_valid: False }`), along with any errors or warnings encountered during validation.
"""

MetadataDefaults = AuthorizationServerMetadataDefaults
errors: List[AuthServerConfigError] = []
warnings: List[AuthServerConfigWarning] = []
metadata = config.metadata
Expand All @@ -112,9 +113,10 @@ def validate_server_config(
)

# Check if 'authorization_code' grant type is supported
if (
not metadata.grant_types_supported
or "authorization_code" not in metadata.grant_types_supported
if "authorization_code" not in (
metadata.grant_types_supported
if metadata.grant_types_supported is not None
else MetadataDefaults.grant_types_supported.value
):
errors.append(
_create_error(
Expand Down
46 changes: 41 additions & 5 deletions tests/utils/validate_server_config_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,24 @@ def test_valid_server_config(self):
assert not hasattr(result, "errors") or len(result.errors) == 0
assert result.warnings == []

def test_valid_server_config_no_grant_types(self):
config = AuthServerConfig(
type=AuthServerType.OAUTH,
metadata=AuthorizationServerMetadata(
issuer="https://example.com",
authorization_endpoint="https://example.com/oauth/authorize",
token_endpoint="https://example.com/oauth/token",
response_types_supported=["code"],
code_challenge_methods_supported=["S256"],
registration_endpoint="https://example.com/register",
),
)

result = validate_server_config(config)
assert result.is_valid is True
assert not hasattr(result, "errors") or len(result.errors) == 0
assert result.warnings == []

def test_invalid_server_config(self):
config = AuthServerConfig(
type=AuthServerType.OAUTH,
Expand All @@ -42,10 +60,6 @@ def test_invalid_server_config(self):

error_codes = [error.code for error in result.errors]
assert AuthServerConfigErrorCode.CODE_RESPONSE_TYPE_NOT_SUPPORTED in error_codes
assert (
AuthServerConfigErrorCode.AUTHORIZATION_CODE_GRANT_NOT_SUPPORTED
in error_codes
)
assert AuthServerConfigErrorCode.PKCE_NOT_SUPPORTED in error_codes

warning_codes = [warning.code for warning in result.warnings]
Expand Down Expand Up @@ -78,7 +92,7 @@ def test_warning_for_missing_dynamic_registration(self):
)
assert len(result.warnings) == 1

def test_code_challenge_methods(self):
def test_invalid_code_challenge_methods(self):
config = AuthServerConfig(
type=AuthServerType.OAUTH,
metadata=AuthorizationServerMetadata(
Expand All @@ -99,3 +113,25 @@ def test_code_challenge_methods(self):
AuthServerConfigErrorCode.S256_CODE_CHALLENGE_METHOD_NOT_SUPPORTED
in error_codes
)

def test_invalid_grant_type(self):
config = AuthServerConfig(
type=AuthServerType.OAUTH,
metadata=AuthorizationServerMetadata(
issuer="https://example.com",
authorization_endpoint="https://example.com/oauth/authorize",
token_endpoint="https://example.com/oauth/token",
response_types_supported=["code"],
grant_types_supported=[], # Use empty list on purpose to ensure it should be treated correctly
code_challenge_methods_supported=["S256"],
),
)

result = validate_server_config(config)
assert result.is_valid is False

error_codes = [error.code for error in result.errors]
assert (
AuthServerConfigErrorCode.AUTHORIZATION_CODE_GRANT_NOT_SUPPORTED
in error_codes
)