mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-22 05:24:18 +02:00
Rename OAuthProxy -> OAuthDCRProxy
This commit is contained in:
parent
254ff1a25d
commit
dd86edf275
17 changed files with 3416 additions and 2075 deletions
|
|
@ -3,7 +3,7 @@ title: oauth_proxy
|
|||
sidebarTitle: oauth_proxy
|
||||
---
|
||||
|
||||
# `fastmcp.server.auth.oauth_proxy`
|
||||
# `fastmcp.server.auth.oauth_dcr_proxy`
|
||||
|
||||
|
||||
OAuth Proxy Provider for FastMCP.
|
||||
|
|
|
|||
|
|
@ -6,8 +6,10 @@ from .auth import (
|
|||
AuthProvider,
|
||||
)
|
||||
from .providers.jwt import JWTVerifier, StaticTokenVerifier
|
||||
from .oauth_proxy import OAuthProxy
|
||||
from .oauth_dcr_proxy import OAuthDCRProxy
|
||||
|
||||
import warnings
|
||||
import fastmcp
|
||||
|
||||
__all__ = [
|
||||
"AuthProvider",
|
||||
|
|
@ -17,7 +19,7 @@ __all__ = [
|
|||
"StaticTokenVerifier",
|
||||
"RemoteAuthProvider",
|
||||
"AccessToken",
|
||||
"OAuthProxy",
|
||||
"OAuthDCRProxy",
|
||||
]
|
||||
|
||||
|
||||
|
|
@ -27,4 +29,18 @@ def __getattr__(name: str):
|
|||
from .providers.bearer import BearerAuthProvider
|
||||
|
||||
return BearerAuthProvider
|
||||
|
||||
if name == "OAuthProxy":
|
||||
from .oauth_dcr_proxy import OAuthDCRProxy as OAuthProxy
|
||||
|
||||
if fastmcp.settings.deprecation_warnings:
|
||||
warnings.warn(
|
||||
"The `OAuthProxy` class is deprecated "
|
||||
"and has been replaced by `OAuthDCRProxy`. "
|
||||
"This import will be removed in a future version.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return OAuthProxy
|
||||
|
||||
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
|
||||
|
|
|
|||
2022
src/fastmcp/server/auth/oauth_dcr_proxy.py
Normal file
2022
src/fastmcp/server/auth/oauth_dcr_proxy.py
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -17,7 +17,7 @@ from pydantic import AnyHttpUrl, BaseModel, model_validator
|
|||
from typing_extensions import Self
|
||||
|
||||
from fastmcp.server.auth import TokenVerifier
|
||||
from fastmcp.server.auth.oauth_proxy import OAuthProxy
|
||||
from fastmcp.server.auth.oauth_dcr_proxy import OAuthDCRProxy
|
||||
from fastmcp.server.auth.providers.jwt import JWTVerifier
|
||||
from fastmcp.utilities.logging import get_logger
|
||||
|
||||
|
|
@ -169,7 +169,7 @@ class OIDCConfiguration(BaseModel):
|
|||
raise
|
||||
|
||||
|
||||
class OIDCProxy(OAuthProxy):
|
||||
class OIDCProxy(OAuthDCRProxy):
|
||||
"""OAuth provider that wraps OAuthProxy to provide configuration via an OIDC configuration URL.
|
||||
|
||||
This provider makes it easier to add OAuth protection for any upstream provider
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ from key_value.aio.protocols import AsyncKeyValue
|
|||
from pydantic import SecretStr, field_validator
|
||||
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||
|
||||
from fastmcp.server.auth.oauth_proxy import OAuthProxy
|
||||
from fastmcp.server.auth.oauth_dcr_proxy import OAuthDCRProxy
|
||||
from fastmcp.server.auth.providers.jwt import JWTVerifier
|
||||
from fastmcp.settings import ENV_FILE
|
||||
from fastmcp.utilities.auth import parse_scopes
|
||||
|
|
@ -57,7 +57,7 @@ class AzureProviderSettings(BaseSettings):
|
|||
return parse_scopes(v)
|
||||
|
||||
|
||||
class AzureProvider(OAuthProxy):
|
||||
class AzureProvider(OAuthDCRProxy):
|
||||
"""Azure (Microsoft Entra) OAuth provider for FastMCP.
|
||||
|
||||
This provider implements Azure/Microsoft Entra ID authentication using the
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ from pydantic_settings import BaseSettings, SettingsConfigDict
|
|||
|
||||
from fastmcp.server.auth import TokenVerifier
|
||||
from fastmcp.server.auth.auth import AccessToken
|
||||
from fastmcp.server.auth.oauth_proxy import OAuthProxy
|
||||
from fastmcp.server.auth.oauth_dcr_proxy import OAuthDCRProxy
|
||||
from fastmcp.settings import ENV_FILE
|
||||
from fastmcp.utilities.auth import parse_scopes
|
||||
from fastmcp.utilities.logging import get_logger
|
||||
|
|
@ -166,7 +166,7 @@ class GitHubTokenVerifier(TokenVerifier):
|
|||
return None
|
||||
|
||||
|
||||
class GitHubProvider(OAuthProxy):
|
||||
class GitHubProvider(OAuthDCRProxy):
|
||||
"""Complete GitHub OAuth provider for FastMCP.
|
||||
|
||||
This provider makes it trivial to add GitHub OAuth protection to any
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ from pydantic_settings import BaseSettings, SettingsConfigDict
|
|||
|
||||
from fastmcp.server.auth import TokenVerifier
|
||||
from fastmcp.server.auth.auth import AccessToken
|
||||
from fastmcp.server.auth.oauth_proxy import OAuthProxy
|
||||
from fastmcp.server.auth.oauth_dcr_proxy import OAuthDCRProxy
|
||||
from fastmcp.settings import ENV_FILE
|
||||
from fastmcp.utilities.auth import parse_scopes
|
||||
from fastmcp.utilities.logging import get_logger
|
||||
|
|
@ -182,7 +182,7 @@ class GoogleTokenVerifier(TokenVerifier):
|
|||
return None
|
||||
|
||||
|
||||
class GoogleProvider(OAuthProxy):
|
||||
class GoogleProvider(OAuthDCRProxy):
|
||||
"""Complete Google OAuth provider for FastMCP.
|
||||
|
||||
This provider makes it trivial to add Google OAuth protection to any
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ from starlette.responses import JSONResponse
|
|||
from starlette.routing import Route
|
||||
|
||||
from fastmcp.server.auth import AccessToken, RemoteAuthProvider, TokenVerifier
|
||||
from fastmcp.server.auth.oauth_proxy import OAuthProxy
|
||||
from fastmcp.server.auth.oauth_dcr_proxy import OAuthDCRProxy
|
||||
from fastmcp.server.auth.providers.jwt import JWTVerifier
|
||||
from fastmcp.settings import ENV_FILE
|
||||
from fastmcp.utilities.auth import parse_scopes
|
||||
|
|
@ -125,7 +125,7 @@ class WorkOSTokenVerifier(TokenVerifier):
|
|||
return None
|
||||
|
||||
|
||||
class WorkOSProvider(OAuthProxy):
|
||||
class WorkOSProvider(OAuthDCRProxy):
|
||||
"""Complete WorkOS OAuth provider for FastMCP.
|
||||
|
||||
This provider implements WorkOS AuthKit OAuth using the OAuth Proxy pattern.
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ def create_github_server_with_mock_callback(base_url: str) -> FastMCP:
|
|||
import secrets
|
||||
import time
|
||||
|
||||
from fastmcp.server.auth.oauth_proxy import ClientCode
|
||||
from fastmcp.server.auth.oauth_dcr_proxy import ClientCode
|
||||
|
||||
# Generate a fake authorization code
|
||||
fake_code = secrets.token_urlsafe(32)
|
||||
|
|
|
|||
0
tests/server/auth/oauth_dcr_proxy/__init__.py
Normal file
0
tests/server/auth/oauth_dcr_proxy/__init__.py
Normal file
|
|
@ -25,7 +25,7 @@ from starlette.applications import Starlette
|
|||
from starlette.testclient import TestClient
|
||||
|
||||
from fastmcp.server.auth.auth import TokenVerifier
|
||||
from fastmcp.server.auth.oauth_proxy import OAuthProxy
|
||||
from fastmcp.server.auth.oauth_dcr_proxy import OAuthDCRProxy
|
||||
|
||||
|
||||
class MockTokenVerifier(TokenVerifier):
|
||||
|
|
@ -69,7 +69,7 @@ def storage():
|
|||
@pytest.fixture
|
||||
def oauth_proxy_with_storage(storage):
|
||||
"""Create OAuth proxy with explicit storage backend."""
|
||||
return OAuthProxy(
|
||||
return OAuthDCRProxy(
|
||||
upstream_authorization_endpoint="https://github.com/login/oauth/authorize",
|
||||
upstream_token_endpoint="https://github.com/login/oauth/access_token",
|
||||
upstream_client_id="test-upstream-client",
|
||||
|
|
@ -84,7 +84,7 @@ def oauth_proxy_with_storage(storage):
|
|||
@pytest.fixture
|
||||
def oauth_proxy_https():
|
||||
"""OAuthProxy configured with HTTPS base_url for __Host- cookies."""
|
||||
return OAuthProxy(
|
||||
return OAuthDCRProxy(
|
||||
upstream_authorization_endpoint="https://github.com/login/oauth/authorize",
|
||||
upstream_token_endpoint="https://github.com/login/oauth/access_token",
|
||||
upstream_client_id="client-id",
|
||||
|
|
@ -96,7 +96,7 @@ def oauth_proxy_https():
|
|||
|
||||
|
||||
async def _start_flow(
|
||||
proxy: OAuthProxy, client_id: str, redirect: str
|
||||
proxy: OAuthDCRProxy, client_id: str, redirect: str
|
||||
) -> tuple[str, str]:
|
||||
"""Register client and start auth; returns (txn_id, consent_url)."""
|
||||
await proxy.register_client(
|
||||
|
|
@ -503,7 +503,7 @@ class TestStoragePersistence:
|
|||
|
||||
async def test_storage_uses_pydantic_adapter(self, oauth_proxy_with_storage):
|
||||
"""Verify that PydanticAdapter serializes/deserializes correctly."""
|
||||
from fastmcp.server.auth.oauth_proxy import OAuthTransaction
|
||||
from fastmcp.server.auth.oauth_dcr_proxy import OAuthTransaction
|
||||
|
||||
client = OAuthClientInformationFull(
|
||||
client_id="pydantic-test-client",
|
||||
|
|
@ -674,7 +674,7 @@ class TestConsentPageServerIcon:
|
|||
verifier.verify_token = Mock(return_value=None)
|
||||
|
||||
# Create OAuthProxy
|
||||
proxy = OAuthProxy(
|
||||
proxy = OAuthDCRProxy(
|
||||
upstream_authorization_endpoint="https://oauth.example.com/authorize",
|
||||
upstream_token_endpoint="https://oauth.example.com/token",
|
||||
upstream_client_id="upstream-client",
|
||||
|
|
@ -705,7 +705,7 @@ class TestConsentPageServerIcon:
|
|||
await proxy.register_client(client_info)
|
||||
|
||||
# Create a transaction manually
|
||||
from fastmcp.server.auth.oauth_proxy import OAuthTransaction
|
||||
from fastmcp.server.auth.oauth_dcr_proxy import OAuthTransaction
|
||||
|
||||
txn_id = "test-txn-id"
|
||||
transaction = OAuthTransaction(
|
||||
|
|
@ -745,7 +745,7 @@ class TestConsentPageServerIcon:
|
|||
verifier.verify_token = Mock(return_value=None)
|
||||
|
||||
# Create OAuthProxy
|
||||
proxy = OAuthProxy(
|
||||
proxy = OAuthDCRProxy(
|
||||
upstream_authorization_endpoint="https://oauth.example.com/authorize",
|
||||
upstream_token_endpoint="https://oauth.example.com/token",
|
||||
upstream_client_id="upstream-client",
|
||||
|
|
@ -769,7 +769,7 @@ class TestConsentPageServerIcon:
|
|||
await proxy.register_client(client_info)
|
||||
|
||||
# Create a transaction
|
||||
from fastmcp.server.auth.oauth_proxy import OAuthTransaction
|
||||
from fastmcp.server.auth.oauth_dcr_proxy import OAuthTransaction
|
||||
|
||||
txn_id = "test-txn-id"
|
||||
transaction = OAuthTransaction(
|
||||
|
|
@ -811,7 +811,7 @@ class TestConsentPageServerIcon:
|
|||
verifier.verify_token = Mock(return_value=None)
|
||||
|
||||
# Create OAuthProxy
|
||||
proxy = OAuthProxy(
|
||||
proxy = OAuthDCRProxy(
|
||||
upstream_authorization_endpoint="https://oauth.example.com/authorize",
|
||||
upstream_token_endpoint="https://oauth.example.com/token",
|
||||
upstream_client_id="upstream-client",
|
||||
|
|
@ -839,7 +839,7 @@ class TestConsentPageServerIcon:
|
|||
await proxy.register_client(client_info)
|
||||
|
||||
# Create a transaction
|
||||
from fastmcp.server.auth.oauth_proxy import OAuthTransaction
|
||||
from fastmcp.server.auth.oauth_dcr_proxy import OAuthTransaction
|
||||
|
||||
txn_id = "test-txn-id"
|
||||
transaction = OAuthTransaction(
|
||||
1297
tests/server/auth/oauth_dcr_proxy/test_oauth_proxy.py
Normal file
1297
tests/server/auth/oauth_dcr_proxy/test_oauth_proxy.py
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -5,7 +5,7 @@ from mcp.shared.auth import InvalidRedirectUriError
|
|||
from pydantic import AnyUrl
|
||||
|
||||
from fastmcp.server.auth.auth import TokenVerifier
|
||||
from fastmcp.server.auth.oauth_proxy import OAuthProxy, ProxyDCRClient
|
||||
from fastmcp.server.auth.oauth_dcr_proxy import OAuthDCRProxy, ProxyDCRClient
|
||||
|
||||
|
||||
class MockTokenVerifier(TokenVerifier):
|
||||
|
|
@ -103,7 +103,7 @@ class TestOAuthProxyRedirectValidation:
|
|||
|
||||
def test_proxy_default_allows_all(self):
|
||||
"""Test that OAuth proxy defaults to allowing all URIs for DCR compatibility."""
|
||||
proxy = OAuthProxy(
|
||||
proxy = OAuthDCRProxy(
|
||||
upstream_authorization_endpoint="https://auth.example.com/authorize",
|
||||
upstream_token_endpoint="https://auth.example.com/token",
|
||||
upstream_client_id="test-client",
|
||||
|
|
@ -119,7 +119,7 @@ class TestOAuthProxyRedirectValidation:
|
|||
"""Test OAuth proxy with custom redirect patterns."""
|
||||
custom_patterns = ["http://localhost:*", "https://*.myapp.com/*"]
|
||||
|
||||
proxy = OAuthProxy(
|
||||
proxy = OAuthDCRProxy(
|
||||
upstream_authorization_endpoint="https://auth.example.com/authorize",
|
||||
upstream_token_endpoint="https://auth.example.com/token",
|
||||
upstream_client_id="test-client",
|
||||
|
|
@ -133,7 +133,7 @@ class TestOAuthProxyRedirectValidation:
|
|||
|
||||
def test_proxy_empty_list_validation(self):
|
||||
"""Test OAuth proxy with empty list (allow none)."""
|
||||
proxy = OAuthProxy(
|
||||
proxy = OAuthDCRProxy(
|
||||
upstream_authorization_endpoint="https://auth.example.com/authorize",
|
||||
upstream_token_endpoint="https://auth.example.com/token",
|
||||
upstream_client_id="test-client",
|
||||
|
|
@ -149,7 +149,7 @@ class TestOAuthProxyRedirectValidation:
|
|||
"""Test that registered clients use the configured patterns."""
|
||||
custom_patterns = ["https://app.example.com/*"]
|
||||
|
||||
proxy = OAuthProxy(
|
||||
proxy = OAuthDCRProxy(
|
||||
upstream_authorization_endpoint="https://auth.example.com/authorize",
|
||||
upstream_token_endpoint="https://auth.example.com/token",
|
||||
upstream_client_id="test-client",
|
||||
|
|
@ -181,7 +181,7 @@ class TestOAuthProxyRedirectValidation:
|
|||
"""Test that unregistered clients return None."""
|
||||
custom_patterns = ["http://localhost:*", "http://127.0.0.1:*"]
|
||||
|
||||
proxy = OAuthProxy(
|
||||
proxy = OAuthDCRProxy(
|
||||
upstream_authorization_endpoint="https://auth.example.com/authorize",
|
||||
upstream_token_endpoint="https://auth.example.com/token",
|
||||
upstream_client_id="test-client",
|
||||
|
|
@ -12,7 +12,7 @@ from key_value.aio.stores.memory import MemoryStore
|
|||
from mcp.shared.auth import OAuthClientInformationFull
|
||||
from pydantic import AnyUrl
|
||||
|
||||
from fastmcp.server.auth.oauth_proxy import OAuthProxy
|
||||
from fastmcp.server.auth.oauth_dcr_proxy import OAuthDCRProxy
|
||||
|
||||
|
||||
class TestOAuthProxyStorage:
|
||||
|
|
@ -39,9 +39,9 @@ class TestOAuthProxyStorage:
|
|||
"""Create in-memory storage for testing."""
|
||||
return MemoryStore()
|
||||
|
||||
def create_proxy(self, jwt_verifier, storage=None) -> OAuthProxy:
|
||||
def create_proxy(self, jwt_verifier, storage=None) -> OAuthDCRProxy:
|
||||
"""Create an OAuth proxy with specified storage."""
|
||||
return OAuthProxy(
|
||||
return OAuthDCRProxy(
|
||||
upstream_authorization_endpoint="https://github.com/login/oauth/authorize",
|
||||
upstream_token_endpoint="https://github.com/login/oauth/access_token",
|
||||
upstream_client_id="test-client-id",
|
||||
|
|
@ -109,7 +109,7 @@ class TestOAuthProxyStorage:
|
|||
self, jwt_verifier, temp_storage
|
||||
):
|
||||
"""Test that ProxyDCRClient is created with redirect URI patterns."""
|
||||
proxy = OAuthProxy(
|
||||
proxy = OAuthDCRProxy(
|
||||
upstream_authorization_endpoint="https://github.com/login/oauth/authorize",
|
||||
upstream_token_endpoint="https://github.com/login/oauth/access_token",
|
||||
upstream_client_id="test-client-id",
|
||||
|
|
@ -27,7 +27,7 @@ from starlette.routing import Route
|
|||
|
||||
from fastmcp import FastMCP
|
||||
from fastmcp.server.auth.auth import AccessToken, RefreshToken, TokenVerifier
|
||||
from fastmcp.server.auth.oauth_proxy import OAuthProxy
|
||||
from fastmcp.server.auth.oauth_dcr_proxy import OAuthDCRProxy
|
||||
from fastmcp.server.auth.providers.jwt import JWTVerifier
|
||||
|
||||
# =============================================================================
|
||||
|
|
@ -311,7 +311,7 @@ def jwt_verifier():
|
|||
@pytest.fixture
|
||||
def oauth_proxy(jwt_verifier):
|
||||
"""Create a standard OAuthProxy instance for testing."""
|
||||
return OAuthProxy(
|
||||
return OAuthDCRProxy(
|
||||
upstream_authorization_endpoint="https://github.com/login/oauth/authorize",
|
||||
upstream_token_endpoint="https://github.com/login/oauth/access_token",
|
||||
upstream_client_id="test-client-id",
|
||||
|
|
@ -341,7 +341,7 @@ class TestOAuthProxyInitialization:
|
|||
|
||||
def test_basic_initialization(self, jwt_verifier):
|
||||
"""Test basic proxy initialization with required parameters."""
|
||||
proxy = OAuthProxy(
|
||||
proxy = OAuthDCRProxy(
|
||||
upstream_authorization_endpoint="https://auth.example.com/authorize",
|
||||
upstream_token_endpoint="https://auth.example.com/token",
|
||||
upstream_client_id="client-123",
|
||||
|
|
@ -361,7 +361,7 @@ class TestOAuthProxyInitialization:
|
|||
|
||||
def test_all_optional_parameters(self, jwt_verifier):
|
||||
"""Test initialization with all optional parameters."""
|
||||
proxy = OAuthProxy(
|
||||
proxy = OAuthDCRProxy(
|
||||
upstream_authorization_endpoint="https://auth.example.com/authorize",
|
||||
upstream_token_endpoint="https://auth.example.com/token",
|
||||
upstream_client_id="client-123",
|
||||
|
|
@ -387,7 +387,7 @@ class TestOAuthProxyInitialization:
|
|||
|
||||
def test_redirect_path_normalization(self, jwt_verifier):
|
||||
"""Test that redirect_path is normalized with leading slash."""
|
||||
proxy = OAuthProxy(
|
||||
proxy = OAuthDCRProxy(
|
||||
upstream_authorization_endpoint="https://auth.com/authorize",
|
||||
upstream_token_endpoint="https://auth.com/token",
|
||||
upstream_client_id="client",
|
||||
|
|
@ -485,7 +485,7 @@ class TestOAuthProxyPKCE:
|
|||
|
||||
@pytest.fixture
|
||||
def proxy_with_pkce(self, jwt_verifier):
|
||||
return OAuthProxy(
|
||||
return OAuthDCRProxy(
|
||||
upstream_authorization_endpoint="https://oauth.example.com/authorize",
|
||||
upstream_token_endpoint="https://oauth.example.com/token",
|
||||
upstream_client_id="upstream-client",
|
||||
|
|
@ -497,7 +497,7 @@ class TestOAuthProxyPKCE:
|
|||
|
||||
@pytest.fixture
|
||||
def proxy_without_pkce(self, jwt_verifier):
|
||||
return OAuthProxy(
|
||||
return OAuthDCRProxy(
|
||||
upstream_authorization_endpoint="https://oauth.example.com/authorize",
|
||||
upstream_token_endpoint="https://oauth.example.com/token",
|
||||
upstream_client_id="upstream-client",
|
||||
|
|
@ -583,7 +583,7 @@ class TestOAuthProxyTokenEndpointAuth:
|
|||
def test_token_auth_method_initialization(self, jwt_verifier):
|
||||
"""Test different token endpoint auth methods."""
|
||||
# client_secret_post
|
||||
proxy_post = OAuthProxy(
|
||||
proxy_post = OAuthDCRProxy(
|
||||
upstream_authorization_endpoint="https://oauth.example.com/authorize",
|
||||
upstream_token_endpoint="https://oauth.example.com/token",
|
||||
upstream_client_id="client",
|
||||
|
|
@ -595,7 +595,7 @@ class TestOAuthProxyTokenEndpointAuth:
|
|||
assert proxy_post._token_endpoint_auth_method == "client_secret_post"
|
||||
|
||||
# client_secret_basic (default)
|
||||
proxy_basic = OAuthProxy(
|
||||
proxy_basic = OAuthDCRProxy(
|
||||
upstream_authorization_endpoint="https://oauth.example.com/authorize",
|
||||
upstream_token_endpoint="https://oauth.example.com/token",
|
||||
upstream_client_id="client",
|
||||
|
|
@ -607,7 +607,7 @@ class TestOAuthProxyTokenEndpointAuth:
|
|||
assert proxy_basic._token_endpoint_auth_method == "client_secret_basic"
|
||||
|
||||
# None (use authlib default)
|
||||
proxy_default = OAuthProxy(
|
||||
proxy_default = OAuthDCRProxy(
|
||||
upstream_authorization_endpoint="https://oauth.example.com/authorize",
|
||||
upstream_token_endpoint="https://oauth.example.com/token",
|
||||
upstream_client_id="client",
|
||||
|
|
@ -619,7 +619,7 @@ class TestOAuthProxyTokenEndpointAuth:
|
|||
|
||||
async def test_token_auth_method_passed_to_client(self, jwt_verifier):
|
||||
"""Test that auth method is passed to AsyncOAuth2Client."""
|
||||
proxy = OAuthProxy(
|
||||
proxy = OAuthDCRProxy(
|
||||
upstream_authorization_endpoint="https://oauth.example.com/authorize",
|
||||
upstream_token_endpoint="https://oauth.example.com/token",
|
||||
upstream_client_id="client-id",
|
||||
|
|
@ -637,7 +637,9 @@ class TestOAuthProxyTokenEndpointAuth:
|
|||
)
|
||||
|
||||
# Mock the upstream OAuth provider response
|
||||
with patch("fastmcp.server.auth.oauth_proxy.AsyncOAuth2Client") as MockClient:
|
||||
with patch(
|
||||
"fastmcp.server.auth.oauth_dcr_proxy.AsyncOAuth2Client"
|
||||
) as MockClient:
|
||||
mock_client = AsyncMock()
|
||||
|
||||
# Mock initial token exchange (authorization code flow)
|
||||
|
|
@ -665,7 +667,7 @@ class TestOAuthProxyTokenEndpointAuth:
|
|||
await proxy.register_client(client)
|
||||
|
||||
# Store client code that would be created during OAuth callback
|
||||
from fastmcp.server.auth.oauth_proxy import ClientCode
|
||||
from fastmcp.server.auth.oauth_dcr_proxy import ClientCode
|
||||
|
||||
client_code = ClientCode(
|
||||
code="test-auth-code",
|
||||
|
|
@ -740,7 +742,7 @@ class TestOAuthProxyE2E:
|
|||
async def test_full_oauth_flow_with_mock_provider(self, mock_oauth_provider):
|
||||
"""Test complete OAuth flow with mock provider."""
|
||||
# Create proxy pointing to mock provider
|
||||
proxy = OAuthProxy(
|
||||
proxy = OAuthDCRProxy(
|
||||
upstream_authorization_endpoint=mock_oauth_provider.authorize_endpoint,
|
||||
upstream_token_endpoint=mock_oauth_provider.token_endpoint,
|
||||
upstream_client_id="mock-client",
|
||||
|
|
@ -793,7 +795,7 @@ class TestOAuthProxyE2E:
|
|||
|
||||
async def test_token_refresh_with_mock_provider(self, mock_oauth_provider):
|
||||
"""Test token refresh flow with mock provider."""
|
||||
proxy = OAuthProxy(
|
||||
proxy = OAuthDCRProxy(
|
||||
upstream_authorization_endpoint=mock_oauth_provider.authorize_endpoint,
|
||||
upstream_token_endpoint=mock_oauth_provider.token_endpoint,
|
||||
upstream_client_id="mock-client",
|
||||
|
|
@ -818,7 +820,9 @@ class TestOAuthProxyE2E:
|
|||
"scope": "read write",
|
||||
}
|
||||
|
||||
with patch("fastmcp.server.auth.oauth_proxy.AsyncOAuth2Client") as MockClient:
|
||||
with patch(
|
||||
"fastmcp.server.auth.oauth_dcr_proxy.AsyncOAuth2Client"
|
||||
) as MockClient:
|
||||
mock_client = AsyncMock()
|
||||
|
||||
# Mock initial token exchange to get FastMCP tokens
|
||||
|
|
@ -847,7 +851,7 @@ class TestOAuthProxyE2E:
|
|||
MockClient.return_value = mock_client
|
||||
|
||||
# Store client code that would be created during OAuth callback
|
||||
from fastmcp.server.auth.oauth_proxy import ClientCode
|
||||
from fastmcp.server.auth.oauth_dcr_proxy import ClientCode
|
||||
|
||||
client_code = ClientCode(
|
||||
code="test-auth-code",
|
||||
|
|
@ -907,7 +911,7 @@ class TestOAuthProxyE2E:
|
|||
"""Test PKCE validation with mock provider."""
|
||||
mock_oauth_provider.require_pkce = True
|
||||
|
||||
proxy = OAuthProxy(
|
||||
proxy = OAuthDCRProxy(
|
||||
upstream_authorization_endpoint=mock_oauth_provider.authorize_endpoint,
|
||||
upstream_token_endpoint=mock_oauth_provider.token_endpoint,
|
||||
upstream_client_id="mock-client",
|
||||
|
|
@ -961,7 +965,7 @@ class TestParameterForwarding:
|
|||
@pytest.fixture
|
||||
def proxy_with_extra_params(self, jwt_verifier):
|
||||
"""Create OAuthProxy with extra parameters configured."""
|
||||
return OAuthProxy(
|
||||
return OAuthDCRProxy(
|
||||
upstream_authorization_endpoint="https://oauth.example.com/authorize",
|
||||
upstream_token_endpoint="https://oauth.example.com/token",
|
||||
upstream_client_id="upstream-client",
|
||||
|
|
@ -975,7 +979,7 @@ class TestParameterForwarding:
|
|||
@pytest.fixture
|
||||
def proxy_without_extra_params(self, jwt_verifier):
|
||||
"""Create OAuthProxy without extra parameters."""
|
||||
return OAuthProxy(
|
||||
return OAuthDCRProxy(
|
||||
upstream_authorization_endpoint="https://oauth.example.com/authorize",
|
||||
upstream_token_endpoint="https://oauth.example.com/token",
|
||||
upstream_client_id="upstream-client",
|
||||
|
|
@ -1121,7 +1125,7 @@ class TestParameterForwarding:
|
|||
|
||||
async def test_multiple_extra_params(self, jwt_verifier):
|
||||
"""Test multiple extra parameters can be configured and forwarded."""
|
||||
proxy = OAuthProxy(
|
||||
proxy = OAuthDCRProxy(
|
||||
upstream_authorization_endpoint="https://oauth.example.com/authorize",
|
||||
upstream_token_endpoint="https://oauth.example.com/token",
|
||||
upstream_client_id="upstream-client",
|
||||
|
|
@ -1182,7 +1186,7 @@ class TestParameterForwarding:
|
|||
from starlette.applications import Starlette
|
||||
from starlette.testclient import TestClient
|
||||
|
||||
proxy = OAuthProxy(
|
||||
proxy = OAuthDCRProxy(
|
||||
upstream_authorization_endpoint="https://oauth.example.com/authorize",
|
||||
upstream_token_endpoint="https://oauth.example.com/token",
|
||||
upstream_client_id="upstream-client",
|
||||
|
|
@ -1233,7 +1237,7 @@ class TestTokenHandlerErrorTransformation:
|
|||
"""Test that client authentication failures return invalid_client with 401."""
|
||||
from mcp.server.auth.handlers.token import TokenErrorResponse
|
||||
|
||||
from fastmcp.server.auth.oauth_proxy import TokenHandler
|
||||
from fastmcp.server.auth.oauth_dcr_proxy import TokenHandler
|
||||
|
||||
handler = TokenHandler(provider=Mock(), client_authenticator=Mock())
|
||||
|
||||
|
|
@ -1257,7 +1261,7 @@ class TestTokenHandlerErrorTransformation:
|
|||
"""Test that grant type authorization errors stay as unauthorized_client with 400."""
|
||||
from mcp.server.auth.handlers.token import TokenErrorResponse
|
||||
|
||||
from fastmcp.server.auth.oauth_proxy import TokenHandler
|
||||
from fastmcp.server.auth.oauth_dcr_proxy import TokenHandler
|
||||
|
||||
handler = TokenHandler(provider=Mock(), client_authenticator=Mock())
|
||||
|
||||
|
|
@ -1277,7 +1281,7 @@ class TestTokenHandlerErrorTransformation:
|
|||
"""Test that other error types pass through unchanged."""
|
||||
from mcp.server.auth.handlers.token import TokenErrorResponse
|
||||
|
||||
from fastmcp.server.auth.oauth_proxy import TokenHandler
|
||||
from fastmcp.server.auth.oauth_dcr_proxy import TokenHandler
|
||||
|
||||
handler = TokenHandler(provider=Mock(), client_authenticator=Mock())
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue