@@ -603,6 +603,16 @@ def _select_authorization_server(self, advertised: list[str]) -> str:
603603 """Which of the servers listed in protected resource metadata to use: the first (the list is never empty)."""
604604 return advertised[0]
605605
606+ def _needs_token_refresh(self) -> bool:
607+ return (not self.context.is_token_valid()) and self.context.can_refresh_token()
608+
609+ def _unauthorized_token_changed(self, response: httpx2.Response, sent_access_token: str | None) -> bool:
610+ """True when a 401 is stale because another request already replaced the access token."""
611+ if response.status_code != 401:
612+ return False
613+ current = self.context.current_tokens.access_token if self.context.current_tokens else None
614+ return current is not None and current != sent_access_token
615+
606616 def _expected_issuer(self) -> str:
607617 """The issuer that authorization server metadata and client credentials must belong to: the
608618 PRM-advertised server, or on the legacy no-PRM path the resource server's origin, which is what
@@ -626,14 +636,13 @@ async def _auth_flow(self, request: httpx2.Request) -> AsyncGenerator[httpx2.Req
626636
627637 # Capture protocol version from request headers
628638 self.context.protocol_version = request.headers.get(MCP_PROTOCOL_VERSION_HEADER)
629- if not self.context.is_token_valid() and self.context.can_refresh_token():
630- needs_refresh = True
639+ needs_refresh = self._needs_token_refresh()
631640
632641 if needs_refresh:
633642 async with self.context.refresh_lock:
634643 refresh_request = None
635644 async with self.context.lock:
636- if not self.context.is_token_valid() and self.context.can_refresh_token ():
645+ if self._needs_token_refresh ():
637646 refresh_request = await self._refresh_token()
638647 if refresh_request is not None:
639648 refresh_response = yield refresh_request
@@ -654,12 +663,7 @@ async def _auth_flow(self, request: httpx2.Request) -> AsyncGenerator[httpx2.Req
654663
655664 if response.status_code == 401 or step_up:
656665 async with self.context.lock:
657- current_access_token = self.context.current_tokens.access_token if self.context.current_tokens else None
658- if (
659- response.status_code == 401
660- and current_access_token is not None
661- and current_access_token != sent_access_token
662- ):
666+ if self._unauthorized_token_changed(response, sent_access_token):
663667 # Another request refreshed or re-authorized while this one was in flight.
664668 self._add_auth_header(request)
665669 yield request
0 commit comments