|
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