fix(auth): check token validity after clock re-sync before attempting refresh

After re-syncing the clock offset, the code now checks whether the token
is actually still valid using the corrected time (via tokenHasExpired()).
If the token is valid, no refresh is needed — the token only appeared
expired due to clock drift. This avoids the impossible situation of
retrying a token refresh when the triggering error was itself a refresh
error.
This commit is contained in:
copilot-swe-agent[bot]
2026-07-03 13:16:28 +00:00
committed by GitHub
parent dc214beb29
commit 078c921d27
@@ -188,12 +188,21 @@ export class RedirectAuthService extends AuthService {
map(({ event }) => event as OAuthErrorEvent),
switchMap(() => this._timeSyncService.checkTimeSync(this.oauthService.clockSkewInSec)),
filter((timeSync) => timeSync?.outOfSync),
// Re-sync the clock with the detected server time and attempt a token refresh
// Re-sync the clock with the detected server time; then check whether the
// token is actually still valid with the corrected clock. Only attempt a
// refresh if the token is truly expired — retrying a refresh when the
// triggering error was itself a token_refresh_error would just fail again.
switchMap((timeSync) =>
this._timeSyncService.syncClockOffset().pipe(
switchMap(() => from(this.oauthService.refreshToken())),
map(() => null as TimeSync | null),
catchError(() => of(timeSync))
switchMap(() => {
if (!this.tokenHasExpired()) {
return of(null as TimeSync | null);
}
return from(this.oauthService.refreshToken()).pipe(
map(() => null as TimeSync | null),
catchError(() => of(timeSync))
);
})
)
),
filter((timeSync): timeSync is TimeSync => timeSync !== null),