mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-31 17:38:48 +00:00
[ADF-4665] [ADF] - Application is refreshed when you have two instances of application opened (#4849)
* refactoring getValueFromToken and fix user token refresh * refactoring getValueFromToken and fix user token refresh * refactoring getValueFromToken and fix user token refres * fix unit test
This commit is contained in:
@@ -21,12 +21,10 @@ import { setupTestBed } from '../testing/setupTestBed';
|
||||
import { CoreTestingModule } from '../testing/core.testing.module';
|
||||
import { AuthGuardSsoRoleService } from './auth-guard-sso-role.service';
|
||||
import { JwtHelperService } from './jwt-helper.service';
|
||||
import { StorageService } from './storage.service';
|
||||
|
||||
describe('Auth Guard SSO role service', () => {
|
||||
|
||||
let authGuard: AuthGuardSsoRoleService;
|
||||
let storageService: StorageService;
|
||||
let jwtHelperService: JwtHelperService;
|
||||
let routerService: Router;
|
||||
|
||||
@@ -36,14 +34,13 @@ describe('Auth Guard SSO role service', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
localStorage.clear();
|
||||
storageService = TestBed.get(StorageService);
|
||||
authGuard = TestBed.get(AuthGuardSsoRoleService);
|
||||
jwtHelperService = TestBed.get(JwtHelperService);
|
||||
routerService = TestBed.get(Router);
|
||||
});
|
||||
|
||||
it('Should canActivate be true if the Role is present int the JWT token', async(() => {
|
||||
spyOn(storageService, 'getItem').and.returnValue('my-access_token');
|
||||
spyOn(localStorage, 'getItem').and.returnValue('my-access_token');
|
||||
spyOn(jwtHelperService, 'decodeToken').and.returnValue({ 'realm_access': { roles: ['role1'] } });
|
||||
|
||||
const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot();
|
||||
@@ -53,7 +50,7 @@ describe('Auth Guard SSO role service', () => {
|
||||
}));
|
||||
|
||||
it('Should canActivate be false if the Role is not present int the JWT token', async(() => {
|
||||
spyOn(storageService, 'getItem').and.returnValue('my-access_token');
|
||||
spyOn(localStorage, 'getItem').and.returnValue('my-access_token');
|
||||
spyOn(jwtHelperService, 'decodeToken').and.returnValue({ 'realm_access': { roles: ['role3'] } });
|
||||
|
||||
const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot();
|
||||
@@ -63,7 +60,7 @@ describe('Auth Guard SSO role service', () => {
|
||||
}));
|
||||
|
||||
it('Should not redirect if canActivate is', async(() => {
|
||||
spyOn(storageService, 'getItem').and.returnValue('my-access_token');
|
||||
spyOn(localStorage, 'getItem').and.returnValue('my-access_token');
|
||||
spyOn(jwtHelperService, 'decodeToken').and.returnValue({ 'realm_access': { roles: ['role1'] } });
|
||||
spyOn(routerService, 'navigate').and.stub();
|
||||
|
||||
@@ -75,7 +72,7 @@ describe('Auth Guard SSO role service', () => {
|
||||
}));
|
||||
|
||||
it('Should canActivate return false if the data Role to check is empty', async(() => {
|
||||
spyOn(storageService, 'getItem').and.returnValue('my-access_token');
|
||||
spyOn(localStorage, 'getItem').and.returnValue('my-access_token');
|
||||
spyOn(jwtHelperService, 'decodeToken').and.returnValue({ 'realm_access': { roles: ['role1', 'role3'] } });
|
||||
|
||||
const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot();
|
||||
@@ -84,7 +81,7 @@ describe('Auth Guard SSO role service', () => {
|
||||
}));
|
||||
|
||||
it('Should canActivate return false if the realm_access is not present', async(() => {
|
||||
spyOn(storageService, 'getItem').and.returnValue('my-access_token');
|
||||
spyOn(localStorage, 'getItem').and.returnValue('my-access_token');
|
||||
spyOn(jwtHelperService, 'decodeToken').and.returnValue({});
|
||||
|
||||
const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot();
|
||||
@@ -93,7 +90,7 @@ describe('Auth Guard SSO role service', () => {
|
||||
}));
|
||||
|
||||
it('Should redirect to the redirectURL if canActivate is false and redirectUrl is in data', async(() => {
|
||||
spyOn(storageService, 'getItem').and.returnValue('my-access_token');
|
||||
spyOn(localStorage, 'getItem').and.returnValue('my-access_token');
|
||||
spyOn(jwtHelperService, 'decodeToken').and.returnValue({});
|
||||
spyOn(routerService, 'navigate').and.stub();
|
||||
|
||||
@@ -105,7 +102,7 @@ describe('Auth Guard SSO role service', () => {
|
||||
}));
|
||||
|
||||
it('Should not redirect if canActivate is false and redirectUrl is not in data', async(() => {
|
||||
spyOn(storageService, 'getItem').and.returnValue('my-access_token');
|
||||
spyOn(localStorage, 'getItem').and.returnValue('my-access_token');
|
||||
spyOn(jwtHelperService, 'decodeToken').and.returnValue({});
|
||||
spyOn(routerService, 'navigate').and.stub();
|
||||
|
||||
@@ -140,7 +137,7 @@ describe('Auth Guard SSO role service', () => {
|
||||
|
||||
it('Should canActivate be true if both Real Role and Client Role are present int the JWT token', () => {
|
||||
const route: ActivatedRouteSnapshot = new ActivatedRouteSnapshot();
|
||||
spyOn(storageService, 'getItem').and.returnValue('my-access_token');
|
||||
spyOn(localStorage, 'getItem').and.returnValue('my-access_token');
|
||||
|
||||
spyOn(jwtHelperService, 'decodeToken').and.returnValue({
|
||||
'realm_access': { roles: ['role1'] },
|
||||
@@ -155,7 +152,7 @@ describe('Auth Guard SSO role service', () => {
|
||||
|
||||
it('Should canActivate be false if the Client Role is not present int the JWT token with the correct role', () => {
|
||||
const route: ActivatedRouteSnapshot = new ActivatedRouteSnapshot();
|
||||
spyOn(storageService, 'getItem').and.returnValue('my-access_token');
|
||||
spyOn(localStorage, 'getItem').and.returnValue('my-access_token');
|
||||
|
||||
spyOn(jwtHelperService, 'decodeToken').and.returnValue({
|
||||
'realm_access': { roles: ['role1'] },
|
||||
@@ -171,7 +168,7 @@ describe('Auth Guard SSO role service', () => {
|
||||
describe('ClientRole ', () => {
|
||||
|
||||
it('Should be true if the resource_access contains the single role', () => {
|
||||
spyOn(storageService, 'getItem').and.returnValue('my-access_token');
|
||||
spyOn(localStorage, 'getItem').and.returnValue('my-access_token');
|
||||
|
||||
spyOn(jwtHelperService, 'decodeToken').and.returnValue(
|
||||
{
|
||||
@@ -183,7 +180,7 @@ describe('Auth Guard SSO role service', () => {
|
||||
});
|
||||
|
||||
it('Should be true if the resource_access contains at least one of the roles', () => {
|
||||
spyOn(storageService, 'getItem').and.returnValue('my-access_token');
|
||||
spyOn(localStorage, 'getItem').and.returnValue('my-access_token');
|
||||
|
||||
spyOn(jwtHelperService, 'decodeToken').and.returnValue(
|
||||
{
|
||||
@@ -195,7 +192,7 @@ describe('Auth Guard SSO role service', () => {
|
||||
});
|
||||
|
||||
it('Should be false if the resource_access does not contain the role', () => {
|
||||
spyOn(storageService, 'getItem').and.returnValue('my-access_token');
|
||||
spyOn(localStorage, 'getItem').and.returnValue('my-access_token');
|
||||
spyOn(jwtHelperService, 'decodeToken').and.returnValue(
|
||||
{
|
||||
'resource_access': { fakeapp: { roles: ['role3'] } }
|
||||
@@ -205,7 +202,7 @@ describe('Auth Guard SSO role service', () => {
|
||||
});
|
||||
|
||||
it('Should be false if the resource_access does not contain the client role related to the app', () => {
|
||||
spyOn(storageService, 'getItem').and.returnValue('my-access_token');
|
||||
spyOn(localStorage, 'getItem').and.returnValue('my-access_token');
|
||||
spyOn(jwtHelperService, 'decodeToken').and.returnValue(
|
||||
{
|
||||
'resource_access': { anotherfakeapp: { roles: ['role1'] } }
|
||||
|
@@ -56,19 +56,19 @@ export class AuthGuardSsoRoleService implements CanActivate {
|
||||
}
|
||||
|
||||
getRealmRoles(): string[] {
|
||||
const access = this.getValueFromToken<any>('realm_access');
|
||||
const access = this.jwtHelperService.getValueFromLocalAccessToken<any>('realm_access');
|
||||
const roles = access ? access['roles'] : [];
|
||||
return roles;
|
||||
}
|
||||
|
||||
getClientRoles(client: string): string[] {
|
||||
const clientRole = this.getValueFromToken<any>('resource_access')[client];
|
||||
const clientRole = this.jwtHelperService.getValueFromLocalAccessToken<any>('resource_access')[client];
|
||||
const roles = clientRole ? clientRole['roles'] : [];
|
||||
return roles;
|
||||
}
|
||||
|
||||
getAccessToken(): string {
|
||||
return this.storageService.getItem('access_token');
|
||||
return this.storageService.getItem(JwtHelperService.USER_ACCESS_TOKEN);
|
||||
}
|
||||
|
||||
hasRealmRole(role: string): boolean {
|
||||
@@ -104,14 +104,4 @@ export class AuthGuardSsoRoleService implements CanActivate {
|
||||
}
|
||||
return hasRole;
|
||||
}
|
||||
|
||||
getValueFromToken<T>(key: string): T {
|
||||
let value;
|
||||
const accessToken = this.getAccessToken();
|
||||
if (accessToken) {
|
||||
const tokenPayload = this.jwtHelperService.decodeToken(accessToken);
|
||||
value = tokenPayload[key];
|
||||
}
|
||||
return <T> value;
|
||||
}
|
||||
}
|
||||
|
@@ -21,6 +21,7 @@ import { AuthenticationService } from './authentication.service';
|
||||
import { Observable } from 'rxjs';
|
||||
import { AppConfigService } from '../app-config/app-config.service';
|
||||
import { AuthGuardBase } from './auth-guard-base';
|
||||
import { JwtHelperService } from './jwt-helper.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
@@ -29,7 +30,8 @@ export class AuthGuard extends AuthGuardBase {
|
||||
|
||||
ticketChangeBind: any;
|
||||
|
||||
constructor(authenticationService: AuthenticationService,
|
||||
constructor(private jwtHelperService: JwtHelperService,
|
||||
authenticationService: AuthenticationService,
|
||||
router: Router,
|
||||
appConfigService: AppConfigService) {
|
||||
super(authenticationService, router, appConfigService);
|
||||
@@ -47,7 +49,9 @@ export class AuthGuard extends AuthGuardBase {
|
||||
this.ticketChangeRedirect(event, 'BPM');
|
||||
}
|
||||
|
||||
if (event.key === 'id_token' && event.newValue !== event.oldValue) {
|
||||
if (event.key === JwtHelperService.USER_ACCESS_TOKEN &&
|
||||
this.jwtHelperService.getValueFromToken(event.newValue, JwtHelperService.USER_PREFERRED_USERNAME) !==
|
||||
this.jwtHelperService.getValueFromToken(event.oldValue, JwtHelperService.USER_PREFERRED_USERNAME)) {
|
||||
this.ticketChangeRedirect(event, 'ALL');
|
||||
}
|
||||
}
|
||||
|
@@ -25,6 +25,7 @@ import { AppConfigService, AppConfigValues } from '../app-config/app-config.serv
|
||||
import { UserRepresentation } from '@alfresco/js-api';
|
||||
import { map, catchError, tap } from 'rxjs/operators';
|
||||
import { HttpHeaders } from '@angular/common/http';
|
||||
import { JwtHelperService } from './jwt-helper.service';
|
||||
|
||||
const REMEMBER_ME_COOKIE_KEY = 'ALFRESCO_REMEMBER_ME';
|
||||
const REMEMBER_ME_UNTIL = 1000 * 60 * 60 * 24 * 30;
|
||||
@@ -290,7 +291,7 @@ export class AuthenticationService {
|
||||
* @returns Auth token string
|
||||
*/
|
||||
getToken(): string {
|
||||
return localStorage.getItem('access_token');
|
||||
return localStorage.getItem(JwtHelperService.USER_ACCESS_TOKEN);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -22,7 +22,15 @@ import { Injectable } from '@angular/core';
|
||||
})
|
||||
export class JwtHelperService {
|
||||
|
||||
constructor() {}
|
||||
static USER_NAME = 'name';
|
||||
static FAMILY_NAME = 'family_name';
|
||||
static GIVEN_NAME = 'given_name';
|
||||
static USER_EMAIL = 'email';
|
||||
static USER_ACCESS_TOKEN = 'access_token';
|
||||
static USER_PREFERRED_USERNAME = 'preferred_username';
|
||||
|
||||
constructor() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a JSON web token into a JS object.
|
||||
@@ -64,4 +72,29 @@ export class JwtHelperService {
|
||||
}
|
||||
return decodeURIComponent(escape(window.atob(output)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a named value from the user access token.
|
||||
* @param key Key name of the field to retrieve
|
||||
* @returns Value from the token
|
||||
*/
|
||||
getValueFromLocalAccessToken<T>(key: string): T {
|
||||
const accessToken = localStorage.getItem(JwtHelperService.USER_ACCESS_TOKEN);
|
||||
return this.getValueFromToken(accessToken, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a named value from the user access token.
|
||||
* @param key accessToken
|
||||
* @param key Key name of the field to retrieve
|
||||
* @returns Value from the token
|
||||
*/
|
||||
getValueFromToken<T>(accessToken: string, key: string): T {
|
||||
let value;
|
||||
if (accessToken) {
|
||||
const tokenPayload = this.decodeToken(accessToken);
|
||||
value = tokenPayload[key];
|
||||
}
|
||||
return <T> value;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user