1

I have a problem that when I logout and navigate to /, canActivateChild guards are not executed to redirect to login.

My requirement is that none of the app is accessible without login.

Here is my root Route config:

const appRoutes: Routes = [
  {
    path: '',
    pathMatch: 'full',
    redirectTo: '/dashboard',
  },
  {
    path: 'login',
    component: LoginComponent
  },
  {
    path: '',
    runGuardsAndResolvers: 'always',
    children: [
      { path: 'dashboard', component: DashboardComponent },

    ],
    canActivateChild: [AuthGuard],

  }
  // { path: '**', component: PageNotFoundComponent }
];

Here is my AuthGuard (userState) is called from canActivateChild

private userState(nextRoute: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean|UrlTree> {
  return this.auth.authState.pipe(
    first(),
    map(user => {
      if (user != null) {
        return true;
      } else {
        const url = this.router.parseUrl('/login');
        console.log('redirect url', state.url);
        url.queryParams['redirect'] = state.url;
        return url;
      }
    }),
  );
}

On login, I navigate to either / or redirect queryParam, if it exists. On logout, I navigate to /, the idea is that it will redirect to dashboard, and, since dashboard is protected and user is null, go to /login?redirect=dashboard.

Everything works, except the last part. When I logout, it redirects to dashboard but DOES NOT activate the canActivateChild guard, completing the redirect to dashboard with success. If I replace canActivateChild with canActivate, it works as desired.

More details:

f.khantsis
  • 3,256
  • 5
  • 50
  • 67

2 Answers2

0

I don't think you need to use canActivateChild with this. You just need to use canActivate at the top level and that will take care of any children of that route.

E.G:

const appRoutes: Routes = [
    { path: 'login', component: LoginComponent },
    {
        path: 'dashboard',
        canActivate: [AuthGuard],
        children: [
            { path: '', redirectTo: 'overview', pathMatch: 'full' },
            { path: 'overview', component: DashboardComponent }
            // More child routes go here
        }
    }
];

Hope this helps!

AndyOR
  • 304
  • 2
  • 11
  • the problem with this, is that when I navigate from one secured component to another, it won't activate. However I will consider dropping the first route. – f.khantsis Apr 29 '19 at 17:05
  • True, but if you want one particular part of the application to be secure using this method you could just include the '/dashboard' part of the route for all the URLs. This approach would also allow you to create an "unsecured" section of the application where you could put any routes that you do not want the AuthGuard to be activated in. – AndyOR Jun 17 '19 at 16:25
-1

You declare the '' path twice. Perhaps its being caught in the first declaration. I'd suggest you moved the first declaration into the second like so. { path: '', runGuardsAndResolvers: 'always', children: [ { path: '', pathMatch: 'full', redirectTo: 'dashboard' }, { path: 'dashboard', component: DashboardComponent }, ], canActivateChild: [AuthGuard], }

IdiakosE Sunday
  • 112
  • 1
  • 8