Skip to content

Commit

Permalink
[AAE-5414] - SSO Auth Guard - Add the concept of excluded roles (#7222)
Browse files Browse the repository at this point in the history
Co-authored-by: Ardit Domi <arditdomi@apl-c02g64vpmd6t.home>
  • Loading branch information
arditdomi and Ardit Domi committed Aug 24, 2021
1 parent d0e99c6 commit aac821a
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 5 deletions.
6 changes: 3 additions & 3 deletions docs/core/services/auth-guard-sso-role.service.md
Expand Up @@ -24,14 +24,14 @@ const appRoutes: Routes = [
path: 'examplepath',
component: ExampleComponent,
canActivate: [ AuthGuardSsoRoleService ],
data: { roles: ['USER_ROLE1', 'USER_ROLE2']}
data: { roles: ['USER_ROLE1', 'USER_ROLE2'], excludedRoles: ['USER_ROLE3']}
},
...
]
```

If the user now clicks on a link or button that follows this route, they will be not able to access this content if they do not have the Realms roles.
<br />**Note**: An additional role ALFRESCO_ADMINISTRATORS can be used in the roles array, which will result in checking whether the logged in user has Content Admin capabilities or not, as this role is not part of the JWT token it will call a Content API to determine it.
If the user now clicks on a link or button that follows this route, they will be not able to access this content if they do not have the Realms roles. Additionally, the user will not be able to access the resource when they have a role that is part of the excludedRoles array.
<br />**Notes**: An additional role ALFRESCO_ADMINISTRATORS can be used in the roles array, which will result in checking whether the logged in user has Content Admin capabilities or not, as this role is not part of the JWT token it will call a Content API to determine it.


Client role Example
Expand Down
34 changes: 34 additions & 0 deletions lib/core/services/auth-guard-sso-role.service.spec.ts
Expand Up @@ -225,4 +225,38 @@ describe('Auth Guard SSO role service', () => {
expect(getCurrentPersonSpy).not.toHaveBeenCalled();
});
});

describe('Excluded Roles', () => {
it('Should canActivate be false when the user has one of the excluded roles', async () => {
spyOn(peopleContentService, 'getCurrentPerson').and.returnValue(of(getFakeUserWithContentAdminCapability()));
spyOn(jwtHelperService, 'getAccessToken').and.returnValue('my-access_token');
spyOn(jwtHelperService, 'decodeToken').and.returnValue({ 'realm_access': { roles: ['role1'] } });

const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot();
router.data = { 'roles': ['ALFRESCO_ADMINISTRATORS'], 'excludedRoles': ['role1'] };

expect(await authGuard.canActivate(router)).toBeFalsy();
});

it('Should canActivate be true when the user has none of the excluded roles', async () => {
spyOn(jwtHelperService, 'getAccessToken').and.returnValue('my-access_token');
spyOn(jwtHelperService, 'decodeToken').and.returnValue({ 'realm_access': { roles: ['role2'] } });

const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot();
router.data = { 'roles': ['role1', 'role2'], 'excludedRoles': ['role3'] };

expect(await authGuard.canActivate(router)).toBeTruthy();
});

it('Should canActivate be false when the user is a content admin and the ALFRESCO_ADMINISTRATORS role is excluded', async () => {
spyOn(peopleContentService, 'getCurrentPerson').and.returnValue(of(getFakeUserWithContentAdminCapability()));
spyOn(jwtHelperService, 'getAccessToken').and.returnValue('my-access_token');
spyOn(jwtHelperService, 'decodeToken').and.returnValue({ 'realm_access': { roles: ['role1'] } });

const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot();
router.data = { 'roles': ['role1'], 'excludedRoles': ['ALFRESCO_ADMINISTRATORS'] };

expect(await authGuard.canActivate(router)).toBeFalsy();
});
});
});
13 changes: 11 additions & 2 deletions lib/core/services/auth-guard-sso-role.service.ts
Expand Up @@ -39,8 +39,9 @@ export class AuthGuardSsoRoleService implements CanActivate {
if (route.data) {
if (route.data['roles']) {
const rolesToCheck: string[] = route.data['roles'];
const isContentAdmin = rolesToCheck.includes(ContentGroups.ALFRESCO_ADMINISTRATORS) ? await this.peopleContentService.isContentAdmin() : false;
hasRealmRole = this.jwtHelperService.hasRealmRoles(rolesToCheck) || isContentAdmin;
const excludedRoles = route.data['excludedRoles'] || [];
const isContentAdmin = rolesToCheck.includes(ContentGroups.ALFRESCO_ADMINISTRATORS) || excludedRoles.includes(ContentGroups.ALFRESCO_ADMINISTRATORS) ? await this.peopleContentService.isContentAdmin() : false;
hasRealmRole = excludedRoles.length ? this.checkAccessWithExcludedRoles(rolesToCheck, excludedRoles, isContentAdmin) : this.hasRoles(rolesToCheck, isContentAdmin);
}

if (route.data['clientRoles']) {
Expand All @@ -62,4 +63,12 @@ export class AuthGuardSsoRoleService implements CanActivate {

return hasRole;
}

private checkAccessWithExcludedRoles(rolesToCheck: string[], excludedRoles: string[], isContentAdmin: boolean): boolean {
return this.hasRoles(rolesToCheck, isContentAdmin) && !this.hasRoles(excludedRoles, isContentAdmin);
}

private hasRoles(rolesToCheck: string[], isContentAdmin: boolean): boolean {
return rolesToCheck.includes(ContentGroups.ALFRESCO_ADMINISTRATORS) ? this.jwtHelperService.hasRealmRoles(rolesToCheck) || isContentAdmin : this.jwtHelperService.hasRealmRoles(rolesToCheck);
}
}

0 comments on commit aac821a

Please sign in to comment.