0

i've changed my authguard to fetch the user object if it is empty. i'm just storing the token in the storage. i see the console.log "role and user ok" and the correct url /member but it redirects me always to / and not to /member in my case.

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
    if (this.authService.loggedin) {
      if (!this.authService.user) {
        console.log('get user')
        this.authService.getUser().pipe(first()).subscribe((result: any) => {
          console.log(result.user)
          if (route.data.roles && route.data.roles.indexOf(result.user.role.name) === -1) {
            console.log('wrong role')
            this.router.navigate(['/']);
            return false;
          } else {
            console.log('role and user ok')
            console.log(state.url)
            return true;
          }
        });
      } else {
        console.log(this.authService.user)
        console.log('user already set')
        if (route.data.roles && route.data.roles.indexOf(this.authService.user.role.name) === -1) {
          console.log('WRONG ROLE')
          this.router.navigate(['/']);
          return false;
        } else {
          console.log('user and role ok')
          return true;
        }
      }

    } else {
      console.log('redirect to login')
      this.router.navigate(['/login']);
      return false;
    }
  }

AuthService

 public isLoggedIn() {
    if (localStorage.getItem('token')) {
      return true;
    } else {
      return false;
    }
  }

getUser() {
    return this.http.get<any>(environment.apiUrl + '/user').pipe(
      tap(res => this.setSession(res))
    );
  }

thanks

markus
  • 475
  • 10
  • 27

2 Answers2

0

Your problem lies here

this.authService.getUser().pipe(first()).subscribe((result: any) => {
          console.log(result.user)
          if (route.data.roles && route.data.roles.indexOf(result.user.role.name) === -1) {
            console.log('wrong role')
            this.router.navigate(['/']);
            return false;
          } else {
            console.log('role and user ok')
            console.log(state.url)
            return true;
          }
        });

You are subscribing to the pipe, so that is asynchronous, the code flow does not wait for that to return and moves ahead and does not find any value true or false. Basically get rid of the asyc subscribe call and you will be fine, that makes me question why do you want to pipe() it in the first place.

TruckDriver
  • 1,383
  • 13
  • 28
0

canActivate needs to return a boolean value or an Observable of boolean. If you need to perform some asynchronous operation in canActivate, you need to return the observable. Router would then wait until the observable returns a value before activating the route. Otherwise guard would have already completed execution before the asynchronous method returns.

Add a return statement to this.auth.getUser and use map instead of subscribe. The router will now subscribe to the returned observable and wait for the result.

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
  if (this.authService.loggedin) {
    if (!this.authService.user) {
      console.log('get user')
      return this.authService.getUser().pipe(map((result: any) => {
        console.log(result.user)
        if (route.data.roles && route.data.roles.indexOf(result.user.role.name) === -1) {
          console.log('wrong role')
          this.router.navigate(['/']);
          return false;
        } else {
          console.log('role and user ok')
          console.log(state.url)
          return true;
        }
      }));
    } else {
      console.log(this.authService.user)
      console.log('user already set')
      if (route.data.roles && route.data.roles.indexOf(this.authService.user.role.name) === -1) {
        console.log('WRONG ROLE')
        this.router.navigate(['/']);
        return false;
      } else {
        console.log('user and role ok')
        return true;
      }
    }

  } else {
    console.log('redirect to login')
    this.router.navigate(['/login']);
    return false;
  }
}
Johns Mathew
  • 804
  • 5
  • 6