Routes Guards causing wrong Route Navigation behavior

Viewed 1043

I'm having an issue trying to navigate through different routes.

I have two different route modules.

app.routes.ts:

Containing only LoginPage:

export const routes: Routes = [
  {
    path: 'login',
    component: LoginPageComponent,
    canActivate: [PreventLoggedInAccess]
  },
  {
    path: '',
    redirectTo: 'login',
    pathMatch: 'full'
  },
  {
    path: '**',
    redirectTo: 'login'
  }
];

export const Routing: ModuleWithProviders = 
    RouterModule.forRoot(routes, { useHash : true });

With PreventLoggedInAccess.canActivate, that, if the user is already logged in redirects him to the logged in section with /app prefix and child route home. It's defined as:

canActivate(): boolean {
  if (!this._authService.isAuthenticated()) {
      return true;
  }
  this._router.navigate(['/app/home']);
  return false;
}

pages.routes.ts:

Containing all /app subroutes that are accessible only if the user is logged in. This is achieved using AuthGuardService.canActivateChild:

export const pageRoutes: Routes = [
  {
    path: 'app',
    component: PagesComponent,
    canActivateChild: [AuthGuardService],
    children: [
      { path: '', redirectTo: 'home', pathMatch: 'full' },
      { path: 'home', component: HomePageComponent },
      { path: 'contents', component: ContentsComponent },
    ]
  }
];

export const Routing: ModuleWithProviders = RouterModule.forChild(pageRoutes);

With the latter that redirects to /login if the user isn't logged in. It's defined as:

canActivateChild(): boolean {
  if (this._authService.isAuthenticated()) {
      return true;
  }
  this._router.navigate(['login']);
  return false;
}

When I navigate from app/home to app/contents it only goes to ContentsComponent after navigating two times. So, if I do two times this._router.navigate(['app/components']); it works, if I do it only one time, the route changes from app/home to app/route for 1ms and it returns to app/home, while if I do it a second time it changes route. While, if I'm in app/contents and try to navigate to app/home it changes route just fine.

isAuthenticated works fine. Both authguards work just fine, so, if I try to access any app child route when I'm not logged In I get redirected to login and If I try to access login when I'm logged In I get redirected to app/home.

I managed to debug a bit and I noticed the following flow:

  • First attempt - app/home -> app/contents:
    • navigate(['app/contents']) is called
    • PreventLoggedInAccess.canActivate is called
    • AuthGuardService.canActivateChild is called
  • Second attempt - app/home -> app/contents:
    • navigate(['app/contents']) is called
    • AuthGuardService.canActivateChild is called

Of course the expected behavior is the second one.

EDIT

Removing this._router.navigate([/app/home]); from PreventLoggedInAccess.canActivate solves the issue

canActivate(): boolean {
  if (!this._authService.isAuthenticated()) {
      return true;
  }
  return false;
}

But still, I do not understand why PreventLoggedInAccess.canActivate is called when navigating to an app child even though AuthGuardService.canActivateChild is attached to it? Why is it called only on the first attempt?

1 Answers
Related