From 15d82919f5b73b4247ce99d329451854f112a8d8 Mon Sep 17 00:00:00 2001 From: alep85 Date: Tue, 3 Sep 2024 09:26:19 +0200 Subject: [PATCH] AAE-24139 Remove authentication tokens when the token is no longer valid and reload the page to let oauth library refresh the token --- .../auth/oidc/redirect-auth.service.spec.ts | 23 +++++++++++++++ .../lib/auth/oidc/redirect-auth.service.ts | 29 ++++++++++++++++++- 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/lib/core/src/lib/auth/oidc/redirect-auth.service.spec.ts b/lib/core/src/lib/auth/oidc/redirect-auth.service.spec.ts index 6134b276930..9928519bfc8 100644 --- a/lib/core/src/lib/auth/oidc/redirect-auth.service.spec.ts +++ b/lib/core/src/lib/auth/oidc/redirect-auth.service.spec.ts @@ -34,6 +34,7 @@ describe('RedirectAuthService', () => { events: oauthEvents$, configure: () => {}, hasValidAccessToken: jasmine.createSpy().and.returnValue(true), + hasValidIdToken: jasmine.createSpy().and.returnValue(true), setupAutomaticSilentRefresh: () => { mockOauthService.silentRefresh(); mockOauthService.refreshToken(); @@ -53,6 +54,7 @@ describe('RedirectAuthService', () => { TestBed.inject(OAuthService); service = TestBed.inject(RedirectAuthService); + spyOn(service, 'reloadPage').and.callFake(() => {}); spyOn(service, 'ensureDiscoveryDocument').and.resolveTo(true); mockOauthService.getAccessToken = () => 'access-token'; }); @@ -93,4 +95,25 @@ describe('RedirectAuthService', () => { expect(refreshTokenCalled).toBe(true); expect(silentRefreshCalled).toBe(true); }); + + it('should remove all auth items from the storage if access token is set and is not authenticated', () => { + mockOauthService.getAccessToken = () => 'access-token'; + spyOnProperty(service, 'authenticated', 'get').and.returnValue(false); + (mockOauthService.events as Subject).next({ type: 'discovery_document_loaded' } as OAuthEvent); + + expect(mockOAuthStorage.removeItem).toHaveBeenCalledWith('access_token'); + expect(mockOAuthStorage.removeItem).toHaveBeenCalledWith('access_token_stored_at'); + expect(mockOAuthStorage.removeItem).toHaveBeenCalledWith('expires_at'); + expect(mockOAuthStorage.removeItem).toHaveBeenCalledWith('granted_scopes'); + expect(mockOAuthStorage.removeItem).toHaveBeenCalledWith('id_token'); + expect(mockOAuthStorage.removeItem).toHaveBeenCalledWith('id_token_claims_obj'); + expect(mockOAuthStorage.removeItem).toHaveBeenCalledWith('id_token_expires_at'); + expect(mockOAuthStorage.removeItem).toHaveBeenCalledWith('id_token_stored_at'); + expect(mockOAuthStorage.removeItem).toHaveBeenCalledWith('nonce'); + expect(mockOAuthStorage.removeItem).toHaveBeenCalledWith('PKCE_verifier'); + expect(mockOAuthStorage.removeItem).toHaveBeenCalledWith('refresh_token'); + expect(mockOAuthStorage.removeItem).toHaveBeenCalledWith('session_state'); + expect(service.reloadPage).toHaveBeenCalledOnceWith(); + }); + }); 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 edfc2d141a4..7bbeb9b961f 100644 --- a/lib/core/src/lib/auth/oidc/redirect-auth.service.ts +++ b/lib/core/src/lib/auth/oidc/redirect-auth.service.ts @@ -19,7 +19,7 @@ import { Inject, Injectable, inject } from '@angular/core'; import { AuthConfig, AUTH_CONFIG, OAuthErrorEvent, OAuthEvent, OAuthService, OAuthStorage, TokenResponse, LoginOptions, OAuthSuccessEvent } from 'angular-oauth2-oidc'; import { JwksValidationHandler } from 'angular-oauth2-oidc-jwks'; import { from, Observable } from 'rxjs'; -import { distinctUntilChanged, filter, map, shareReplay } from 'rxjs/operators'; +import { distinctUntilChanged, filter, map, shareReplay, take } from 'rxjs/operators'; import { AuthService } from './auth.service'; import { AUTH_MODULE_CONFIG, AuthModuleConfig } from './auth-config'; @@ -53,6 +53,21 @@ export class RedirectAuthService extends AuthService { private authConfig!: AuthConfig | Promise; + private readonly AUTH_STORAGE_ITEMS: string[] = [ + 'access_token', + 'access_token_stored_at', + 'expires_at', + 'granted_scopes', + 'id_token', + 'id_token_claims_obj', + 'id_token_expires_at', + 'id_token_stored_at', + 'nonce', + 'PKCE_verifier', + 'refresh_token', + 'session_state' + ]; + constructor( private oauthService: OAuthService, private _oauthStorage: OAuthStorage, @@ -69,6 +84,13 @@ export class RedirectAuthService extends AuthService { shareReplay(1) ); + this.oauthService.events.pipe(take(1)).subscribe(() => { + if(this.oauthService.getAccessToken() && !this.authenticated){ + this.AUTH_STORAGE_ITEMS.map((item: string) => { this._oauthStorage.removeItem(item); }); + this.reloadPage(); + } + }); + this.onLogin = this.authenticated$.pipe( filter((authenticated) => authenticated), map(() => undefined) @@ -223,4 +245,9 @@ export class RedirectAuthService extends AuthService { updateIDPConfiguration(config: AuthConfig) { this.oauthService.configure(config); } + + reloadPage() { + window.location.reload(); + } + }