From 078c921d274c4d0ff08fd10f60bc46785aecea2b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 3 Jul 2026 13:16:28 +0000 Subject: [PATCH] fix(auth): check token validity after clock re-sync before attempting refresh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- .../src/lib/auth/oidc/redirect-auth.service.ts | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/lib/core/src/lib/auth/oidc/redirect-auth.service.ts b/lib/core/src/lib/auth/oidc/redirect-auth.service.ts index b4ef3b3c4c..d8d991f02d 100644 --- a/lib/core/src/lib/auth/oidc/redirect-auth.service.ts +++ b/lib/core/src/lib/auth/oidc/redirect-auth.service.ts @@ -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),