fix(auth): change token workflow
This commit changes the token refresh, which is now based on an expire token event and should be therefore triggered everytime when a token expires.
MODIFY
src/app/components/swagger/swagger.component.ts
src/app/components/swagger/swagger.component.ts
@@ -109,7 +109,7 @@ export class SwaggerComponent implements OnInit {
}
private setAuthorizationHeader(request: SwaggerUI.Request) {
- const token = this.keycloakHelperService.getTokenFromLocalStorage();
+ const token = this.keycloakHelperService.getToken();
if (token.length > 0) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
request.headers.Authorization = 'Bearer ' + token;

MODIFY
src/app/guards/auth.guard.ts
src/app/guards/auth.guard.ts
@@ -53,7 +53,7 @@ export class AuthGuard extends KeycloakAuthGuard {
}
// we are logged in and can set the tokens and fetch permissions
- this.keycloakHelper.setAndUpdateTokens();
+ this.keycloakHelper.initUpdateTokens();
await this.permissionsService.updateUserPermissions();
return this.authenticated;

MODIFY
src/app/guards/login.guard.ts
src/app/guards/login.guard.ts
@@ -42,7 +42,7 @@ export class LoginGuard extends KeycloakAuthGuard {
});
}
// we are logged in and can set the tokens and fetch permissions
- this.keycloakHelper.setAndUpdateTokens();
+ this.keycloakHelper.initUpdateTokens();
return this.authenticated;
}
}

MODIFY
src/app/services/keycloak-helper/keycloak-helper.service.ts
src/app/services/keycloak-helper/keycloak-helper.service.ts
*/
import { Injectable } from '@angular/core';
-import { KeycloakService } from 'keycloak-angular';
import {
- KeycloakInstance,
- KeycloakProfile,
- KeycloakTokenParsed
-} from 'keycloak-js';
+ KeycloakEvent,
+ KeycloakEventType,
+ KeycloakService
+} from 'keycloak-angular';
+import { KeycloakProfile, KeycloakTokenParsed } from 'keycloak-js';
import { ConfigService } from '../config/config.service';
import { Router } from '@angular/router';
@@ -33,10 +33,6 @@ export class KeycloakHelperService {
private executed = false;
private username?: string;
- private readonly TOKEN = 'APIMAN_DEVPORTAL_KEYCLOAK_SESSION_STORAGE_TOKEN';
- private readonly REFRESH_TOKEN =
- 'APIMAN_DEVPORTAL_KEYCLOAK_SESSION_STORAGE_REFRESH_TOKEN';
-
constructor(
private readonly keycloak: KeycloakService,
private configService: ConfigService,
@@ -56,9 +52,7 @@ export class KeycloakHelperService {
},
initOptions: {
onLoad: 'check-sso',
- checkLoginIframe: false,
- token: localStorage.getItem(this.TOKEN) ?? '',
- refreshToken: localStorage.getItem(this.REFRESH_TOKEN) ?? ''
+ checkLoginIframe: false
},
loadUserProfileAtStartUp: true, // because of https://github.com/mauriciovigolo/keycloak-angular/pull/269
enableBearerInterceptor: true,
@@ -99,7 +93,7 @@ export class KeycloakHelperService {
}
public logout(): void {
- this.clearTokensFromSessionStorage();
+ // this.clearTokensFromSessionStorage();
// remove current angular route so that the base path is still used
const url = window.location.href.replace(this.router.url, '') + '/home';
void this.keycloak.logout(url);
@@ -109,42 +103,22 @@ export class KeycloakHelperService {
* Will set the current tokens after login, and start an automatic refresh of tokens.
* Could be triggered multiple times but should only execute once
*/
- public setAndUpdateTokens(): void {
+ public initUpdateTokens(): void {
if (!this.executed && this.keycloak.getKeycloakInstance().tokenParsed) {
- this.setTokensToLocalStorage(this.keycloak.getKeycloakInstance());
- setInterval(() => {
- this.keycloak
- .updateToken()
- .then(() => {
- this.setTokensToLocalStorage(this.keycloak.getKeycloakInstance());
- })
- .catch(() => {
- console.error('Error refreshing token', new Date());
- this.clearTokensFromSessionStorage();
- });
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- }, Math.min((this.keycloak.getKeycloakInstance().tokenParsed!.exp! - 60) * 1000, 4 * 60 * 1000)); // refresh token minimum every 4 minutes)
+ this.keycloak.keycloakEvents$.subscribe({
+ next: (event: KeycloakEvent) => {
+ if (event.type == KeycloakEventType.OnTokenExpired) {
+ console.info('Try to refresh token');
+ void this.keycloak.updateToken();
}
- this.executed = true;
}
-
- private setTokensToLocalStorage(keycloakInstance: KeycloakInstance) {
- localStorage.setItem(this.TOKEN, keycloakInstance.token ?? '');
- localStorage.setItem(
- this.REFRESH_TOKEN,
- keycloakInstance.refreshToken ?? ''
- );
+ });
}
-
- public getTokenFromLocalStorage(): string {
- // we have to trigger the method here to make sure the tokens are set after a login
- this.setAndUpdateTokens();
- return localStorage.getItem(this.TOKEN) ?? '';
+ this.executed = true;
}
- private clearTokensFromSessionStorage() {
- localStorage.removeItem(this.TOKEN);
- localStorage.removeItem(this.REFRESH_TOKEN);
+ public getToken(): string {
+ return this.keycloak.getKeycloakInstance().token as string;
}
public getUsername(): string {
@@ -157,7 +131,7 @@ export class KeycloakHelperService {
public decodeCurrentKeyloakToken(): KeycloakTokenParsed {
try {
return <KeycloakTokenParsed>(
- JSON.parse(atob(this.getTokenFromLocalStorage().split('.')[1]))
+ JSON.parse(atob(this.getToken().split('.')[1]))
);
} catch (error) {
console.error('Error while decoding keycloak token', error);

fix(auth): change token workflow

This commit changes the token refresh, which is now based on an expire token event and should be therefore triggered everytime when a token expires.