How to get current route guard
Asked Answered
P

5

7

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.

Pieplant answered 8/2, 2017 at 14:19 Comment(4)
Possible duplicate of Authorized vs unauthorized main viewPregnancy
Check this post : #41571437 You just need to setup a service that will check if your user is registered or not, and set your guard with this service.Pregnancy
There are good instruction how to use guards. I already use it. User already on protected page and i should check if session is active without any GUI interaction. I try to do it in my app.component.ts.Pieplant
Could we have some code then if possible ? How do you check if your session is active or anything ? Are you using cookies, localStorage ?Pregnancy
W
5

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.

Whopping answered 31/7, 2017 at 8:17 Comment(1)
Beware: if you have lazy loaded modules (i.e. using loadChildren), the route prefix will not be included in the path property. You can end up with path duplicates... so checking the router URL is not reliable.Whinstone
B
4

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.

Balinese answered 9/5, 2017 at 14:42 Comment(1)
As much as your contribution to the question is valid as it provides rationale for such a functionality, answers are not a place for that. Please use comments section in the future (I know it is still not possible for you, but keep that in mind).Nimbus
S
1

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');
Samp answered 27/9, 2019 at 15:20 Comment(1)
Warning: not working for minified/uglified code because uglifier will change service class name and it will be not AuthGuardService but something primitiveEntomostracan
D
1

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).

Decimal answered 27/9, 2019 at 15:36 Comment(0)
S
0

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.

Supplicant answered 19/7, 2023 at 17:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.