|
2 | 2 | Production-ready OAuth2 Authentication implementation for HTTPX using anyio.
|
3 | 3 |
|
4 | 4 | This module provides a complete OAuth 2.0 authentication implementation
|
5 |
| -that handles authorization code flow with PKCE, automatic token refresh and proper error handling. |
| 5 | +that handles authorization code flow with PKCE, |
| 6 | +automatic token refresh and proper error handling. |
6 | 7 | The callback server implementation should be handled by the calling code.
|
7 | 8 | """
|
8 | 9 |
|
|
12 | 13 | import string
|
13 | 14 | import time
|
14 | 15 | import webbrowser
|
15 |
| -from abc import ABC, abstractmethod |
16 | 16 | from collections.abc import AsyncGenerator, Awaitable, Callable
|
17 | 17 | from urllib.parse import urljoin
|
18 | 18 |
|
19 | 19 | import anyio
|
20 | 20 | import httpx
|
21 | 21 |
|
| 22 | +from mcp.client.token_storage import InMemoryTokenStorage, TokenStorage |
22 | 23 | from mcp.shared.auth import (
|
23 | 24 | OAuthClientInformationFull,
|
24 | 25 | OAuthClientMetadata,
|
|
28 | 29 | from mcp.types import LATEST_PROTOCOL_VERSION
|
29 | 30 |
|
30 | 31 |
|
31 |
| -class TokenStorage(ABC): |
32 |
| - """Abstract base class for token storage implementations.""" |
33 |
| - |
34 |
| - @abstractmethod |
35 |
| - async def get_tokens(self) -> OAuthToken | None: |
36 |
| - """Get stored tokens.""" |
37 |
| - pass |
38 |
| - |
39 |
| - @abstractmethod |
40 |
| - async def set_tokens(self, tokens: OAuthToken) -> None: |
41 |
| - """Store tokens.""" |
42 |
| - pass |
43 |
| - |
44 |
| - @abstractmethod |
45 |
| - async def get_client_info(self) -> OAuthClientInformationFull | None: |
46 |
| - """Get stored client information.""" |
47 |
| - pass |
48 |
| - |
49 |
| - @abstractmethod |
50 |
| - async def set_client_info(self, client_info: OAuthClientInformationFull) -> None: |
51 |
| - """Store client information.""" |
52 |
| - pass |
53 |
| - |
54 |
| - |
55 |
| -class InMemoryTokenStorage(TokenStorage): |
56 |
| - """Simple in-memory token storage implementation.""" |
57 |
| - |
58 |
| - def __init__(self): |
59 |
| - self._tokens: OAuthToken | None = None |
60 |
| - self._client_info: OAuthClientInformationFull | None = None |
61 |
| - |
62 |
| - async def get_tokens(self) -> OAuthToken | None: |
63 |
| - return self._tokens |
64 |
| - |
65 |
| - async def set_tokens(self, tokens: OAuthToken) -> None: |
66 |
| - self._tokens = tokens |
67 |
| - |
68 |
| - async def get_client_info(self) -> OAuthClientInformationFull | None: |
69 |
| - return self._client_info |
70 |
| - |
71 |
| - async def set_client_info(self, client_info: OAuthClientInformationFull) -> None: |
72 |
| - self._client_info = client_info |
73 |
| - |
74 |
| - |
75 | 32 | async def discover_oauth_metadata(server_url: str) -> OAuthMetadata | None:
|
76 | 33 | """
|
77 | 34 | Discovers OAuth metadata from the server's well-known endpoint.
|
|
0 commit comments