I'm working on securing the front-end of my Angular application using route guards. In working with them in the past and researching online, adding multiple guards to a route requires all of them to return true to allow access.
But what if I want just one to return true to allow access? (like || instead of &&)
For example, my route guards look for certain roles in the user's token:
@Injectable()
export class ActiveRoleGuard implements CanActivate {
constructor(private sessionService: SessionService, private router: Router) { }
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
let token = this.sessionService.getToken();
if (!token) {
return false;
}
if (token.role.toLowerCase().indexOf("active") < 0) {
this.router.navigate(["/issue"]);
return false;
}
return true;
}
}
And
@Injectable()
export class AdminRoleGuard implements CanActivate {
constructor(private sessionService: SessionService, private router: Router) { }
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
let token = this.appSessionService.getToken();
if (!token) {
return false;
}
if (token.role.toLowerCase().indexOf("admin") < 0) {
this.router.navigate(["/issue"]);
return false;
}
return true;
}
}
If I was to combine them normally in a router module it would be something like...
{path: "someroute", component: SomeComponent, canActivate: [ActiveRouteGuard, AdminRouteGuard]}
... but that would require a user to be both Active and an Admin. But what if I wanted to enforce being Active and either an Admin or a Manager?
It's simple to enforce on the API like so:
[Authorize(Roles = "Active")]
[Authorize(Roles = "Admin, Manager")]
public class SomeController : ApiController
but how do I do this in Angular?
Rather than having two separate
CanActivateimplementations, you could just use a single version that can be "configured". To do this, you can take advantage of thedataproperty ofRoute. For example, in your routes, you could do something like:Using this, you could take one of your existing
CanActivateimplementations, and make it more generic. You can access therequiredRolesproperty fromdatavia theActivatedRouteSnapshot. e.g:Once you've got this, you can check if the token's role is in the array, etc, etc.
If you have an always-required
Activerole and then a one-ofAdminorManagerrole, you could also extend this to have multipledataproperties. For example, you could haverequiredRolesandatLeastOneOfRolesand update your logic to process that accordingly... There are many options at this point but I don't think you will need help with that.