@@ -180,6 +180,19 @@ def update_token_expiry(self, token: OAuthToken) -> None:
180180 """Update token expiry time using shared util function."""
181181 self .token_expiry_time = calculate_token_expiry (token .expires_in )
182182
183+ def restore_token_expiry (self ) -> None :
184+ """Restore ``token_expiry_time`` from the persisted absolute expiry.
185+
186+ ``_initialize`` reloads ``current_tokens`` from storage, but the stored
187+ ``OAuthToken`` only carries the relative ``expires_in``, so the absolute
188+ expiry must be persisted separately (``expires_at``) and restored here.
189+ Without it, ``is_token_valid()`` treats an already-expired access token
190+ as valid on a fresh process and sends a stale Bearer, wasting a 401
191+ round-trip before re-authentication.
192+ """
193+ if self .current_tokens and self .current_tokens .expires_at is not None :
194+ self .token_expiry_time = self .current_tokens .expires_at
195+
183196 def is_token_valid (self ) -> bool :
184197 """Check if current token is valid."""
185198 return bool (
@@ -484,6 +497,8 @@ async def _handle_token_response(self, response: httpx2.Response) -> None:
484497 # Store tokens in context
485498 self .context .current_tokens = token_response
486499 self .context .update_token_expiry (token_response )
500+ # Persist the absolute expiry so it survives a process restart
501+ token_response .expires_at = self .context .token_expiry_time
487502 await self .context .storage .set_tokens (token_response )
488503
489504 async def _refresh_token (self ) -> httpx2 .Request :
@@ -539,6 +554,7 @@ async def _handle_refresh_response(self, response: httpx2.Response) -> bool:
539554
540555 self .context .current_tokens = token_response
541556 self .context .update_token_expiry (token_response )
557+ token_response .expires_at = self .context .token_expiry_time
542558 await self .context .storage .set_tokens (token_response )
543559
544560 return True
@@ -551,6 +567,7 @@ async def _initialize(self) -> None:
551567 """Load stored tokens and client info."""
552568 self .context .current_tokens = await self .context .storage .get_tokens ()
553569 self .context .client_info = await self .context .storage .get_client_info ()
570+ self .context .restore_token_expiry ()
554571 self ._initialized = True
555572
556573 def _add_auth_header (self , request : httpx2 .Request ) -> None :
0 commit comments