Search code examples
angularangular16angular-guards

Angular guard loop issue


I've been having issues with a guard loop and I'm trying to find out the best routing setup.

Current routing structure...

Root path with a guard on it.

A child dashboard route with a resolver that requires a route param.

A child session route for login sign out etc.

A child error route.

Problems I have...

  1. As part of app initialisation I redirect to sign in. This then triggers the guard which then returns false as user isn't authenticated which then means sign in route isn't activated.

  2. When they're signed in they're navigated back to the root path. Which then kicks off the guard. Problem then becomes that the guard redirects to a child dashboard route. But then gets stuck in a loop because the redirect is to a child of the root the guard is on.

  3. Same issue as 2 but for when an error occurs in guard and try to redirect there

I just can't work out what the correct routing, guard structure should be?


Solution

    • don't redirect at initialization => the guard is supposed to make checks and return an url tree of the login page in case of not authenticated user
    • never make the guard navigate
    • try not to return an url tree in case of success (aka redirect), but return true; as it gets hard to follow the redirections when there are other ways to declare them

    https://angular.io/api/router/CanActivateFn

    Then your routes definition should have guarded routes and others that are not. Otherwise, you will be stuck in a loop

    const appRoutes: Routes = [{
        path: '',
        pathMatch: "full",
        redirectTo: "home"
      },
      {
        path: '', // this path is useless, it's only to group all your protected routes
        canActivate: [AuthGuard],
        children: [
          {
            path: 'other',
            component: OtherComponent,
          },
          {
            path: 'home',
            component: HomeComponent,
          },
        ],
      },
      {
        path: 'login',
        component: LoginComponent,
      },
      {
      /* this one could be protected too, 
         as there is no point in going here in case of authentication error,
         as the user would have to connect again anyway.
         IMO it's better to redirect to the loading page. (and display an error notification)
      */
        path: 'error', 
        component: ErrorComponent
      },
    
      // otherwise redirect to home
      {
        path: '**',
        redirectTo: 'home'
      },
    ];