Reputation: 955
I'm making an app with some protected pages inside This pages are accessible only for registered users. Some times i should check session for timeout or after change browser tab. If user already exit in other tab or session expired, the app should redirect user to login page.
I'm using guards to protect pages so i think it correct way to check current route by his guard. Page should by redirected if user session expired/closed and current route uses certain guard.
Could anybody help to get guards of the current route?
I checked docs for Router and ActivatedRoute and don't find any information about that.
Upvotes: 7
Views: 5245
Reputation: 451
Here's what I think is a better an a more general implementation of a hasGuard check. It checks for existance of an arbitrary guard anywhere on the tree of ActivatedRouteSnapshot given by its root node.
function hasGuard(route: ActivatedRouteSnapshot,
selector: (r : Route) => any[] | undefined,
guard: any) : boolean {
const guards = route.routeConfig ? selector(route.routeConfig) : undefined;
if (guards)
for (const g of guards)
if (g == guard)
return true;
for (const child of route.children)
if (hasGuard(child, selector, guard))
return true;
return false;
}
It can be used, for example, like this:
hasGuard(this.router.routerState.snapshot.root, r => r.canActivate, authGuard)
Here authGuard is the actual CanActivateFn set up in the routes array.
Upvotes: 0
Reputation: 14669
You can put runGuardsAndResolvers: 'always'
in the route(s) configurations, and simply try reloading the route (something like this.router.navigate([], {relativeTo: this.route })
, where route
is the component's instance of ActivatedRoute
).
Upvotes: 1
Reputation: 21
I implemented this solution in the authentication library of my company , you can implement this in a service and consume in any place to check if the current route has implemented your guard
function hasGuard(guardTypeArray: string[], guardName: string) {
const currentRouteConfig = this.router.config.find(f => f.path === this.router.url.substr(1));
let hasGuard = false;
if (currentRouteConfig) {
for (const guardType of guardTypeArray) {
if (!hasGuard) {
if (currentRouteConfig[guardType] ) {
for (const guard of currentRouteConfig[guardType]) {
if (guard.name === guardName) {
hasGuard = true;
break;
}
}
}
} else {
break;
}
}
}
return hasGuard;
}
// Calling it
const check = hasGuard([
'canActivate',
'canActivateChild'
], 'AuthGuardService');
Upvotes: 1
Reputation: 259
I was facing this issue also. So I did a little resarch and fiddling and developed this solution:
Assuming the AuthService is implemented like in https://angular.io/guide/router#canactivate-requiring-authentication.
In the AuthService add the following:
Logout() {
// (logout logic here)
var currentRouteConfig = this.router.config.find(f=>f.path == this.router.url.substr(1));
if(currentRouteConfig != null && currentRouteConfig.CanActivate != null) {
this.redirectUrl = this.router.url;
this.router.navigate(['/login'])
}
The substr(1) just removes the leading '/' as the path in the router config is without it.
Please keep in mind, that this is a naive implementation assuming that the canActivate is always implementing an authentication guard. Other logic may need deeper checking for authentication guards.
Upvotes: 5
Reputation: 116
I face exactly the same issue. Here is a scenario to better understand the need. Imagine you have a website where some pages are protected and some are not. A guard is used to protect appropriate pages. Now imagine user is on protected page (let's say viewing profile) and clicks 'Logout' button. What should happen? User should be redirected to a home page. But if user is on a page that is not protected by guard nothing should really happen. Of course it's possible to check it on every signle page if redirect should happen but it's not the best solution. A better solution would be to handle this situation in AuthService, where logging out is acctually happens but for that someone needs to know if currectly active route is protected by guard or not.
Upvotes: 4