Skip to content

Commit 37a91ab

Browse files
committed
Split _perform_authorization_code_grant code to be able to reuse authorization_url creation
1 parent a9cc822 commit 37a91ab

File tree

1 file changed

+17
-8
lines changed

1 file changed

+17
-8
lines changed

src/mcp/client/auth/oauth2.py

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
import time
1313
from collections.abc import AsyncGenerator, Awaitable, Callable
1414
from dataclasses import dataclass, field
15-
from typing import Any, Protocol
15+
from typing import Any, NewType, Protocol
1616
from urllib.parse import quote, urlencode, urljoin, urlparse
1717

1818
import anyio
@@ -53,6 +53,8 @@
5353

5454
logger = logging.getLogger(__name__)
5555

56+
AuthorizationState = NewType("AuthorizationState", str)
57+
5658

5759
class PKCEParameters(BaseModel):
5860
"""PKCE (Proof Key for Code Exchange) parameters."""
@@ -305,14 +307,10 @@ async def _perform_authorization(self) -> httpx.Request:
305307
token_request = await self._exchange_token_authorization_code(auth_code, code_verifier)
306308
return token_request
307309

308-
async def _perform_authorization_code_grant(self) -> tuple[str, str]:
309-
"""Perform the authorization redirect and get auth code."""
310+
async def _build_authorization_url(self) -> tuple[str, AuthorizationState, PKCEParameters]:
311+
"""Build authorization URL and state."""
310312
if self.context.client_metadata.redirect_uris is None:
311313
raise OAuthFlowError("No redirect URIs provided for authorization code grant") # pragma: no cover
312-
if not self.context.redirect_handler:
313-
raise OAuthFlowError("No redirect handler provided for authorization code grant") # pragma: no cover
314-
if not self.context.callback_handler:
315-
raise OAuthFlowError("No callback handler provided for authorization code grant") # pragma: no cover
316314

317315
if self.context.oauth_metadata and self.context.oauth_metadata.authorization_endpoint:
318316
auth_endpoint = str(self.context.oauth_metadata.authorization_endpoint) # pragma: no cover
@@ -325,7 +323,7 @@ async def _perform_authorization_code_grant(self) -> tuple[str, str]:
325323

326324
# Generate PKCE parameters
327325
pkce_params = PKCEParameters.generate()
328-
state = secrets.token_urlsafe(32)
326+
state = AuthorizationState(secrets.token_urlsafe(32))
329327

330328
auth_params = {
331329
"response_type": "code",
@@ -344,6 +342,17 @@ async def _perform_authorization_code_grant(self) -> tuple[str, str]:
344342
auth_params["scope"] = self.context.client_metadata.scope
345343

346344
authorization_url = f"{auth_endpoint}?{urlencode(auth_params)}"
345+
346+
return authorization_url, state, pkce_params
347+
348+
async def _perform_authorization_code_grant(self) -> tuple[str, str]:
349+
"""Perform the authorization redirect and get auth code."""
350+
if not self.context.redirect_handler:
351+
raise OAuthFlowError("No redirect handler provided for authorization code grant") # pragma: no cover
352+
if not self.context.callback_handler:
353+
raise OAuthFlowError("No callback handler provided for authorization code grant") # pragma: no cover
354+
355+
authorization_url, state, pkce_params = await self._build_authorization_url()
347356
await self.context.redirect_handler(authorization_url)
348357

349358
# Wait for callback

0 commit comments

Comments
 (0)