Skip to content

Commit 2c1c35d

Browse files
committed
Try refresh token first
1 parent 556eebd commit 2c1c35d

File tree

1 file changed

+44
-47
lines changed

1 file changed

+44
-47
lines changed

src/mcp/client/auth.py

Lines changed: 44 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -520,59 +520,56 @@ async def async_auth_flow(self, request: httpx.Request) -> AsyncGenerator[httpx.
520520
# Capture protocol version from request headers
521521
self.context.protocol_version = request.headers.get(MCP_PROTOCOL_VERSION)
522522

523+
if not self.context.is_token_valid() and self.context.can_refresh_token():
524+
# Try to refresh token
525+
refresh_request = await self._refresh_token()
526+
refresh_response = yield refresh_request
527+
528+
if not await self._handle_refresh_response(refresh_response):
529+
# Refresh failed, need full re-authentication
530+
self._initialized = False
531+
523532
if self.context.is_token_valid():
524533
self._add_auth_header(request)
525534

526535
response = yield request
527536

528537
if response.status_code == 401:
529-
if self.context.can_refresh_token():
530-
# Try to refresh token
531-
refresh_request = await self._refresh_token()
532-
refresh_response = yield refresh_request
533-
534-
if not await self._handle_refresh_response(refresh_response):
535-
# Refresh failed, need full re-authentication
536-
self._initialized = False
537-
else:
538-
self.context.clear_tokens()
539-
540-
# If we don't have valid tokens after refresh, perform OAuth flow
541-
if not self.context.is_token_valid():
542-
try:
543-
# OAuth flow must be inline due to generator constraints
544-
# Step 1: Discover protected resource metadata (RFC9728 with WWW-Authenticate support)
545-
discovery_request = await self._discover_protected_resource(response)
546-
discovery_response = yield discovery_request
547-
await self._handle_protected_resource_response(discovery_response)
548-
549-
# Step 2: Discover OAuth metadata (with fallback for legacy servers)
550-
oauth_request = await self._discover_oauth_metadata()
551-
oauth_response = yield oauth_request
552-
handled = await self._handle_oauth_metadata_response(oauth_response, is_fallback=False)
553-
554-
# If path-aware discovery failed with 404, try fallback to root
555-
if not handled:
556-
fallback_request = await self._discover_oauth_metadata_fallback()
557-
fallback_response = yield fallback_request
558-
await self._handle_oauth_metadata_response(fallback_response, is_fallback=True)
559-
560-
# Step 3: Register client if needed
561-
registration_request = await self._register_client()
562-
if registration_request:
563-
registration_response = yield registration_request
564-
await self._handle_registration_response(registration_response)
565-
566-
# Step 4: Perform authorization
567-
auth_code, code_verifier = await self._perform_authorization()
568-
569-
# Step 5: Exchange authorization code for tokens
570-
token_request = await self._exchange_token(auth_code, code_verifier)
571-
token_response = yield token_request
572-
await self._handle_token_response(token_response)
573-
except Exception:
574-
logger.exception("OAuth flow error")
575-
raise
538+
# Perform full OAuth flow
539+
try:
540+
# OAuth flow must be inline due to generator constraints
541+
# Step 1: Discover protected resource metadata (RFC9728 with WWW-Authenticate support)
542+
discovery_request = await self._discover_protected_resource(response)
543+
discovery_response = yield discovery_request
544+
await self._handle_protected_resource_response(discovery_response)
545+
546+
# Step 2: Discover OAuth metadata (with fallback for legacy servers)
547+
oauth_request = await self._discover_oauth_metadata()
548+
oauth_response = yield oauth_request
549+
handled = await self._handle_oauth_metadata_response(oauth_response, is_fallback=False)
550+
551+
# If path-aware discovery failed with 404, try fallback to root
552+
if not handled:
553+
fallback_request = await self._discover_oauth_metadata_fallback()
554+
fallback_response = yield fallback_request
555+
await self._handle_oauth_metadata_response(fallback_response, is_fallback=True)
556+
557+
# Step 3: Register client if needed
558+
registration_request = await self._register_client()
559+
if registration_request:
560+
registration_response = yield registration_request
561+
await self._handle_registration_response(registration_response)
562+
563+
# Step 4: Perform authorization
564+
auth_code, code_verifier = await self._perform_authorization()
565+
566+
# Step 5: Exchange authorization code for tokens
567+
token_request = await self._exchange_token(auth_code, code_verifier)
568+
token_response = yield token_request
569+
await self._handle_token_response(token_response)
570+
except Exception:
571+
logger.exception("OAuth flow error")
572+
raise
576573

577574
# Retry with new tokens
578575
self._add_auth_header(request)

0 commit comments

Comments
 (0)