Use MemoryStore for OAuth proxy tests

Updated all OAuthProxy test instantiations to use MemoryStore instead of defaulting to DiskStore, avoiding SQLite timeout issues on Windows and improving test performance.

Co-authored-by: Bill Easton <strawgate@users.noreply.github.com>
This commit is contained in:
claude[bot] 2026-02-01 02:30:05 +00:00
commit cec40b378d
10 changed files with 51 additions and 0 deletions

View file

@ -288,6 +288,8 @@ def jwt_verifier():
@pytest.fixture
def oauth_proxy(jwt_verifier):
"""Create a standard OAuthProxy instance for testing."""
from key_value.aio.stores.memory import MemoryStore
return OAuthProxy(
upstream_authorization_endpoint="https://github.com/login/oauth/authorize",
upstream_token_endpoint="https://github.com/login/oauth/access_token",
@ -297,6 +299,7 @@ def oauth_proxy(jwt_verifier):
base_url="https://myserver.com",
redirect_path="/auth/callback",
jwt_signing_key="test-secret",
client_storage=MemoryStore(),
)

View file

@ -3,6 +3,7 @@
from urllib.parse import parse_qs, urlparse
import pytest
from key_value.aio.stores.memory import MemoryStore
from mcp.server.auth.provider import AuthorizationParams
from mcp.shared.auth import OAuthClientInformationFull
from pydantic import AnyUrl
@ -67,6 +68,7 @@ class TestOAuthProxyPKCE:
base_url="https://proxy.example.com",
forward_pkce=True,
jwt_signing_key="test-secret",
client_storage=MemoryStore(),
)
@pytest.fixture
@ -82,6 +84,7 @@ class TestOAuthProxyPKCE:
base_url="https://proxy.example.com",
forward_pkce=False,
jwt_signing_key="test-secret",
client_storage=MemoryStore(),
)
async def test_pkce_forwarding_enabled(self, proxy_with_pkce):
@ -172,6 +175,7 @@ class TestParameterForwarding:
"prompt": "consent",
"max_age": "3600",
},
client_storage=MemoryStore(),
)
client = OAuthClientInformationFull(

View file

@ -1,6 +1,7 @@
"""Tests for OAuth proxy configuration and validation."""
import pytest
from key_value.aio.stores.memory import MemoryStore
from mcp.server.auth.provider import AuthorizationParams, AuthorizeError
from mcp.shared.auth import OAuthClientInformationFull
from pydantic import AnyHttpUrl, AnyUrl
@ -76,6 +77,7 @@ class TestResourceURLValidation:
token_verifier=jwt_verifier,
base_url="https://proxy.example.com",
jwt_signing_key="test-secret",
client_storage=MemoryStore(),
)
# Use non-default path to prove fix isn't relying on old hardcoded /mcp
proxy.set_mcp_path("/api/v2/mcp")
@ -261,6 +263,7 @@ class TestResourceURLValidation:
token_verifier=jwt_verifier,
base_url="https://proxy.example.com",
jwt_signing_key="test-secret",
client_storage=MemoryStore(),
)
proxy.set_mcp_path("/mcp")
# Simulate server configured with query params for tenant scoping
@ -300,6 +303,7 @@ class TestResourceURLValidation:
token_verifier=jwt_verifier,
base_url="https://proxy.example.com",
jwt_signing_key="test-secret",
client_storage=MemoryStore(),
)
proxy.set_mcp_path("/mcp")
# Simulate server configured with query params for tenant scoping
@ -337,6 +341,7 @@ class TestResourceURLValidation:
token_verifier=jwt_verifier,
base_url="https://proxy.example.com",
jwt_signing_key="test-secret",
client_storage=MemoryStore(),
)
proxy.set_mcp_path("/mcp")
# Simulate server configured with query params for tenant scoping
@ -374,6 +379,7 @@ class TestResourceURLValidation:
token_verifier=jwt_verifier,
base_url="https://proxy.example.com",
jwt_signing_key="test-secret",
client_storage=MemoryStore(),
)
# Before set_mcp_path, _jwt_issuer is None
@ -397,6 +403,7 @@ class TestResourceURLValidation:
token_verifier=jwt_verifier,
base_url="https://proxy.example.com",
jwt_signing_key="test-secret",
client_storage=MemoryStore(),
)
proxy.set_mcp_path(None)
@ -413,6 +420,7 @@ class TestResourceURLValidation:
token_verifier=jwt_verifier,
base_url="https://proxy.example.com",
jwt_signing_key="test-secret",
client_storage=MemoryStore(),
)
with pytest.raises(RuntimeError) as exc_info:
@ -430,6 +438,7 @@ class TestResourceURLValidation:
token_verifier=jwt_verifier,
base_url="https://proxy.example.com",
jwt_signing_key="test-secret",
client_storage=MemoryStore(),
)
# Before get_routes, _jwt_issuer is None

View file

@ -5,6 +5,7 @@ from unittest.mock import AsyncMock, patch
from urllib.parse import parse_qs, urlparse
import httpx
from key_value.aio.stores.memory import MemoryStore
from mcp.server.auth.provider import AuthorizationCode, AuthorizationParams
from mcp.shared.auth import OAuthClientInformationFull
from pydantic import AnyUrl
@ -30,6 +31,7 @@ class TestOAuthProxyE2E:
token_verifier=MockTokenVerifier(),
base_url="http://localhost:8000",
jwt_signing_key="test-secret",
client_storage=MemoryStore(),
)
# Create FastMCP server with proxy
@ -84,6 +86,7 @@ class TestOAuthProxyE2E:
token_verifier=MockTokenVerifier(),
base_url="http://localhost:8000",
jwt_signing_key="test-secret",
client_storage=MemoryStore(),
)
# Initialize JWT issuer before token operations
@ -201,6 +204,7 @@ class TestOAuthProxyE2E:
base_url="http://localhost:8000",
forward_pkce=True, # Enable PKCE forwarding
jwt_signing_key="test-secret",
client_storage=MemoryStore(),
)
client = OAuthClientInformationFull(

View file

@ -1,5 +1,7 @@
"""Tests for OAuth proxy initialization and configuration."""
from key_value.aio.stores.memory import MemoryStore
from fastmcp.server.auth.oauth_proxy import OAuthProxy
@ -16,6 +18,7 @@ class TestOAuthProxyInitialization:
token_verifier=jwt_verifier,
base_url="https://api.example.com",
jwt_signing_key="test-secret",
client_storage=MemoryStore(),
)
assert (
@ -45,6 +48,7 @@ class TestOAuthProxyInitialization:
forward_pkce=False,
token_endpoint_auth_method="client_secret_post",
jwt_signing_key="test-secret",
client_storage=MemoryStore(),
)
assert proxy._upstream_revocation_endpoint == "https://auth.example.com/revoke"
@ -65,5 +69,6 @@ class TestOAuthProxyInitialization:
base_url="https://api.com",
redirect_path="auth/callback", # No leading slash
jwt_signing_key="test-secret",
client_storage=MemoryStore(),
)
assert proxy._redirect_path == "/auth/callback"

View file

@ -4,6 +4,7 @@ import time
from unittest.mock import AsyncMock, Mock, patch
import pytest
from key_value.aio.stores.memory import MemoryStore
from mcp.server.auth.handlers.token import TokenErrorResponse
from mcp.server.auth.handlers.token import TokenHandler as SDKTokenHandler
from mcp.server.auth.provider import AuthorizationCode
@ -35,6 +36,7 @@ class TestOAuthProxyTokenEndpointAuth:
base_url="https://proxy.example.com",
token_endpoint_auth_method="client_secret_post",
jwt_signing_key="test-secret",
client_storage=MemoryStore(),
)
assert proxy_post._token_endpoint_auth_method == "client_secret_post"
@ -48,6 +50,7 @@ class TestOAuthProxyTokenEndpointAuth:
base_url="https://proxy.example.com",
token_endpoint_auth_method="client_secret_basic",
jwt_signing_key="test-secret",
client_storage=MemoryStore(),
)
assert proxy_basic._token_endpoint_auth_method == "client_secret_basic"
@ -60,6 +63,7 @@ class TestOAuthProxyTokenEndpointAuth:
token_verifier=jwt_verifier,
base_url="https://proxy.example.com",
jwt_signing_key="test-secret",
client_storage=MemoryStore(),
)
assert proxy_default._token_endpoint_auth_method is None
@ -74,6 +78,7 @@ class TestOAuthProxyTokenEndpointAuth:
base_url="https://proxy.example.com",
token_endpoint_auth_method="client_secret_post",
jwt_signing_key="test-secret",
client_storage=MemoryStore(),
)
# Initialize JWT issuer before token operations
@ -296,6 +301,7 @@ class TestFallbackAccessTokenExpiry:
base_url="http://localhost:8000",
jwt_signing_key="test-signing-key",
fallback_access_token_expiry_seconds=86400,
client_storage=MemoryStore(),
)
assert provider._fallback_access_token_expiry_seconds == 86400
@ -313,6 +319,7 @@ class TestFallbackAccessTokenExpiry:
),
base_url="http://localhost:8000",
jwt_signing_key="test-signing-key",
client_storage=MemoryStore(),
)
assert provider._fallback_access_token_expiry_seconds is None
@ -345,6 +352,7 @@ class TestUpstreamTokenStorageTTL:
token_verifier=jwt_verifier,
base_url="https://proxy.example.com",
jwt_signing_key="test-secret-key",
client_storage=MemoryStore(),
)
proxy.set_mcp_path("/mcp")
return proxy

View file

@ -2,6 +2,7 @@
from unittest.mock import Mock
from key_value.aio.stores.memory import MemoryStore
from starlette.requests import Request
from starlette.responses import HTMLResponse
@ -76,6 +77,7 @@ class TestErrorPageRendering:
),
base_url="http://localhost:8000",
jwt_signing_key="test-signing-key",
client_storage=MemoryStore(),
)
# Mock a request with an error from the IdP

View file

@ -29,6 +29,8 @@ class TestEnhancedAuthorizationHandler:
@pytest.fixture
def oauth_proxy(self, rsa_key_pair):
"""Create OAuth proxy for testing."""
from key_value.aio.stores.memory import MemoryStore
return OAuthProxy(
upstream_authorization_endpoint="https://github.com/login/oauth/authorize",
upstream_token_endpoint="https://github.com/login/oauth/access_token",
@ -42,6 +44,7 @@ class TestEnhancedAuthorizationHandler:
),
base_url="https://myserver.com",
jwt_signing_key="test-secret",
client_storage=MemoryStore(),
)
def test_unregistered_client_returns_html_for_browser(self, oauth_proxy):
@ -290,6 +293,8 @@ class TestContentNegotiation:
@pytest.fixture
def oauth_proxy(self):
"""Create OAuth proxy for testing."""
from key_value.aio.stores.memory import MemoryStore
return OAuthProxy(
upstream_authorization_endpoint="https://github.com/login/oauth/authorize",
upstream_token_endpoint="https://github.com/login/oauth/access_token",
@ -303,6 +308,7 @@ class TestContentNegotiation:
),
base_url="https://myserver.com",
jwt_signing_key="test-secret",
client_storage=MemoryStore(),
)
def test_html_preferred_when_both_accepted(self, oauth_proxy):

View file

@ -8,6 +8,7 @@ The fix uses MCP SDK 1.17+ which implements RFC 9728 path-scoped well-known URLs
import httpx
import pytest
from key_value.aio.stores.memory import MemoryStore
from pydantic import AnyHttpUrl
from starlette.applications import Starlette
from starlette.routing import Mount
@ -220,6 +221,7 @@ class TestOAuthMounting:
token_verifier=token_verifier,
base_url="https://api.example.com/api", # Includes mount prefix
issuer_url="https://api.example.com", # Root level
client_storage=MemoryStore(),
)
mcp = FastMCP("test-server", auth=auth_provider)
@ -290,6 +292,7 @@ class TestOAuthMounting:
upstream_client_secret="test-client-secret",
token_verifier=token_verifier,
base_url="https://api.example.com/api", # Has path, no explicit issuer_url
client_storage=MemoryStore(),
)
mcp = FastMCP("test-server", auth=auth_provider)
@ -366,6 +369,7 @@ class TestOAuthMounting:
token_verifier=token_verifier,
base_url="https://api.example.com/api",
issuer_url="https://api.example.com", # Explicitly root
client_storage=MemoryStore(),
)
well_known_routes = auth_provider.get_well_known_routes(mcp_path="/mcp")

View file

@ -1,6 +1,7 @@
"""Tests for OAuth proxy redirect URI validation."""
import pytest
from key_value.aio.stores.memory import MemoryStore
from mcp.shared.auth import InvalidRedirectUriError
from pydantic import AnyUrl
@ -112,6 +113,7 @@ class TestOAuthProxyRedirectValidation:
token_verifier=MockTokenVerifier(),
base_url="http://localhost:8000",
jwt_signing_key="test-secret",
client_storage=MemoryStore(),
)
# The proxy should store None for default (allow all)
@ -130,6 +132,7 @@ class TestOAuthProxyRedirectValidation:
base_url="http://localhost:8000",
allowed_client_redirect_uris=custom_patterns,
jwt_signing_key="test-secret",
client_storage=MemoryStore(),
)
assert proxy._allowed_client_redirect_uris == custom_patterns
@ -145,6 +148,7 @@ class TestOAuthProxyRedirectValidation:
base_url="http://localhost:8000",
allowed_client_redirect_uris=[],
jwt_signing_key="test-secret",
client_storage=MemoryStore(),
)
assert proxy._allowed_client_redirect_uris == []
@ -162,6 +166,7 @@ class TestOAuthProxyRedirectValidation:
base_url="http://localhost:8000",
allowed_client_redirect_uris=custom_patterns,
jwt_signing_key="test-secret",
client_storage=MemoryStore(),
)
# Register a client
@ -195,6 +200,7 @@ class TestOAuthProxyRedirectValidation:
base_url="http://localhost:8000",
allowed_client_redirect_uris=custom_patterns,
jwt_signing_key="test-secret",
client_storage=MemoryStore(),
)
# Get an unregistered client