Home > Software engineering >  Angular navigate causing infinte loop in route guarding
Angular navigate causing infinte loop in route guarding

Time:12-27

I have these routes:

  {path: '', redirectTo: 'login', pathMatch: 'full'},
  {path: 'todos', component: TodosComponent, canActivate: [AuthGuard]},
  {path: 'add-todo', component: AddTodoComponent, canActivate: [AuthGuard]},
  {path: 'todo/:id', component: TodoComponent, resolve: {
    todo: TodoResolver
  },  canActivate: [AuthGuard]
},
  {path: 'login', component: LoginComponent, canActivate: [IsLoggedIn]},
  {path: '**', redirectTo: ''}
]

With this guard:

export class IsLoggedInGuard implements CanActivate {
  constructor(private storageService: StorageService, private router: Router, private authService: AuthService) {}

  canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
    const user = this.storageService.getFromStorage('user');
    if(user) {
      this.authService.setUser(user, false);
      this.router.navigate(['todos']);
      return false;
    }
    return true;
  }
}

Locally works fine, but when I deploy it it enters an infinite loop.

Why is there an infinte loop and how can I solve it?

CodePudding user response:

Most probably you are entering an infinite loop because the / path is being redirected to a path which is protected by the AuthGuard itself.

So for example. You try to access Route A, which is protected by the guard, which redirects to route B (the base route / ), and route B could be redirecting (view redirectTo attributes in the route) to route C which is also protected by the AuthGuard, resulting in the following routes.

A -> B -> C -> B -> C...

Your guard should be

export class IsLoggedInGuard implements CanActivate {
   constructor(private storageService: StorageService, private router: 
    Router, private authService: AuthService) {}

    canActivate(
       route: ActivatedRouteSnapshot,
       state: RouterStateSnapshot
   ): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean 
      | UrlTree {

       const user = this.storageService.getFromStorage('user');
       if(user) {
         this.authService.setUser(user, false);
         this.router.navigate(['todos']);
       }
   
      return true;
  }
}

Make sure that the routing definition is correct.

Thanks!

CodePudding user response:

To fix this issue, you should make sure that the IsLoggedInGuard guard is only applied to the login route, and not to any other routes. You can do this by modifying the route configuration like this:

{
  path: 'login',
  component: LoginComponent,
  canActivate: [IsLoggedInGuard]
},
{
  path: 'todos',
  component: TodosComponent,
  canActivate: [AuthGuard]
},
{
  path: 'add-todo',
  component: AddTodoComponent,
  canActivate: [AuthGuard]
},
{
  path: 'todo/:id',
  component: TodoComponent,
  resolve: {
    todo: TodoResolver
  },
  canActivate: [AuthGuard]
},
  • Related