mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2026-09-09 18:03:21 +00:00
refactor: remove tokenHasExpiredDueToClockOutOfSync$ and re-sync clock + refresh token on validation failure
Instead of having a separate observable that detects token expiration due to clock drift and immediately logs the user out, the oauthErrorEventOccurDueToClockOutOfSync$ now re-syncs the clock offset and attempts a token refresh when clock drift is detected. Only if the refresh fails after re-syncing does it propagate the error and trigger logout.
This commit is contained in:
@@ -29,12 +29,12 @@ import {
|
||||
OAuthLogger
|
||||
} from 'angular-oauth2-oidc';
|
||||
import { WebCryptoJwksValidationHandler } from './web-crypto-jwks-validation-handler';
|
||||
import { from, Observable, race, ReplaySubject } from 'rxjs';
|
||||
import { distinctUntilChanged, filter, map, scan, shareReplay, skip, switchMap, take } from 'rxjs/operators';
|
||||
import { from, Observable, of, race, ReplaySubject } from 'rxjs';
|
||||
import { catchError, distinctUntilChanged, filter, map, scan, shareReplay, switchMap, take } from 'rxjs/operators';
|
||||
import { AuthService } from './auth.service';
|
||||
import { AUTH_MODULE_CONFIG, AuthModuleConfig } from './auth-config';
|
||||
import { RetryLoginService } from './retry-login.service';
|
||||
import { TimeSyncService } from '../services/time-sync.service';
|
||||
import { TimeSync, TimeSyncService } from '../services/time-sync.service';
|
||||
|
||||
const isPromise = <T>(value: T | Promise<T>): value is Promise<T> => value && typeof (value as Promise<T>).then === 'function';
|
||||
|
||||
@@ -89,15 +89,11 @@ export class RedirectAuthService extends AuthService {
|
||||
*/
|
||||
secondTokenRefreshErrorEventOccur$: Observable<OAuthErrorEvent>;
|
||||
|
||||
/**
|
||||
* Observable that emits an error when the token has expired due to
|
||||
* the local machine clock being out of sync with the server time.
|
||||
*/
|
||||
tokenHasExpiredDueToClockOutOfSync$: Observable<Error>;
|
||||
|
||||
/**
|
||||
* Observable that emits an error when the OAuth error event occurs due to
|
||||
* the local machine clock being out of sync with the server time.
|
||||
* When clock drift is detected, it re-syncs the clock and requests a new token
|
||||
* before propagating the error (if the refresh still fails).
|
||||
*/
|
||||
oauthErrorEventOccurDueToClockOutOfSync$: Observable<Error>;
|
||||
|
||||
@@ -192,6 +188,15 @@ 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
|
||||
switchMap((timeSync) =>
|
||||
this._timeSyncService.syncClockOffset().pipe(
|
||||
switchMap(() => from(this.oauthService.refreshToken())),
|
||||
map(() => null as TimeSync | null),
|
||||
catchError(() => of(timeSync))
|
||||
)
|
||||
),
|
||||
filter((timeSync): timeSync is TimeSync => timeSync !== null),
|
||||
map(
|
||||
(timeSync) =>
|
||||
new Error(
|
||||
@@ -207,24 +212,6 @@ export class RedirectAuthService extends AuthService {
|
||||
shareReplay(1)
|
||||
);
|
||||
|
||||
this.tokenHasExpiredDueToClockOutOfSync$ = this.oauthService.events.pipe(
|
||||
map(() => !!this.oauthService.getIdentityClaims() && this.tokenHasExpired()),
|
||||
filter((hasExpired) => hasExpired),
|
||||
// Skip the first occurrence: the library will attempt an automatic token
|
||||
// refresh. Only check for clock drift if the token is still expired after
|
||||
// that refresh attempt has had a chance to run.
|
||||
skip(1),
|
||||
switchMap(() => this._timeSyncService.checkTimeSync(this.oauthService.clockSkewInSec)),
|
||||
filter((timeSync) => timeSync?.outOfSync),
|
||||
map(
|
||||
(timeSync) =>
|
||||
new Error(
|
||||
`Token has expired due to local machine clock ${timeSync.localDateTimeISO} being out of sync with server time ${timeSync.serverDateTimeISO}`
|
||||
)
|
||||
),
|
||||
take(1)
|
||||
);
|
||||
|
||||
this.onLogout$ = this.oauthService.events.pipe(
|
||||
filter((event) => event.type === 'logout'),
|
||||
map(() => undefined)
|
||||
@@ -233,7 +220,6 @@ export class RedirectAuthService extends AuthService {
|
||||
this.combinedOAuthErrorsStream$ = race([
|
||||
this.oauthErrorEventOccurDueToClockOutOfSync$,
|
||||
this.firstOauthErrorEventExcludingTokenRefreshError$,
|
||||
this.tokenHasExpiredDueToClockOutOfSync$,
|
||||
this.secondTokenRefreshErrorEventOccur$
|
||||
]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user