Home > OS >  Infinite loop using window.location on an Angular Guard
Infinite loop using window.location on an Angular Guard

Time:03-09

So i need to start this Angular13 application based on the user role trough a JWT. If the user is "superorganizer" then i need to render certain view but if the user is "organizer" then i need to render another view.

After some research I tried to use a canActivate Guard from Angular, it was a success but i have a problem right now:

I have an infinite loop if the user is not a "superorganizer" becouse of the redirect with "window.location.href".

I looked for many solutions but cant resolve my problem.

Here is my AuthService:

import { UserModel } from '../models/user.model';

@Injectable({
  providedIn: 'root'
})
export class AuthService {

  // superorganizer: string = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImZlZHBhdDAxIiwibmFtZSI6Ik5pY28gQWx2YXJleiIsInJvbGUiOiJzdXBlcm9yZ2FuaXplciJ9.qsWFtsv8mA0gpqF_JFmMVNZyT9QptkrUnjmhIA-KGDI"

  user!: UserModel;
  hardcodedJWT: string = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImZlZHBhdDAxIiwibmFtZSI6Ik5pY28gQWx2YXJleiIsInJvbGUiOiJvcmdhbml6ZXIifQ.6ppbCs-_L2aUVfTiz5ONIVTBP8H9ON2u9CGjpZnWzsE"



  constructor() { }
 
  getUser(): UserModel {
   this.user = JSON.parse(atob(this.hardcodedJWT.split('.')[1]));
   console.log(this.user);
   return this.user;
  }
}

Here is my Guard:

import { ActivatedRouteSnapshot, CanActivate, CanLoad, Route, RouterStateSnapshot, UrlSegment, UrlTree } from '@angular/router';
import { Observable } from 'rxjs';
import { AuthService } from '../services/auth.service';

@Injectable({
  providedIn: 'root'
})
export class AuthGuard implements CanActivate {

  constructor(private authService: AuthService) { }

  canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
      this.authService.getUser();
      if(!this.authService.user.role.includes('superorganizer') ) {
       window.location.href='http://localhost:4200/organizer';
        
      }
      return this.authService.user.role.includes(route.data.role);
  }
}

And finally, here is my app-routing.module:

import { Routes, RouterModule } from '@angular/router';
import { OrganizerComponent } from './organizer/organizer.component';
import { SuperOrganizerComponent } from './super-organizer/super-organizer.component';
import { AuthGuard } from './guards/auth.guard';

const routes: Routes = [

  {
    path: '',
    component: SuperOrganizerComponent,
    canActivate: [AuthGuard],
    data: {
      role: 'superorganizer'
    }
  },
  {
    path: 'organizer',
    component: OrganizerComponent,
    canActivate: [AuthGuard],
    data: {
      role: 'organizer'
    }
  },
  {
    path: '**',
    redirectTo: '',
  }

]


@NgModule({
  imports: [
    RouterModule.forRoot(routes)
  ],
  exports: [RouterModule]
})
export class AppRoutingModule { }

Thank you in advance for any idea on this problem

CodePudding user response:

You should just change url through router service, not directly through url in the browser, example of code below:

export class AuthGuard implements CanActivate {

  constructor(private authService: AuthService) { }

  canActivate(
    route: ActivatedRouteSnapshot,
    router: Router,
    state: RouterStateSnapshot
  ) {
      this.authService.getUser();

      if(!this.authService.user.role.includes('superorganizer') ) {
        this.router.navigateByUrl('/organizer');
        return false;
      }

      return this.authService.user.role.includes(route.data.role);
  }
}
  • Related