Volodymyr Humeniuk
Volodymyr Humeniuk

Reputation: 3791

Angular router guard with Observable does not work after page refresh

I have the next Angular Guard:

export class AdminGuard implements CanActivate {
  constructor(
    private readonly router: Router,
    private readonly userService: UserService
  ) { }

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

      return this.userService.getUserRoles().pipe(
        map(roles => {
          if (roles.admin) {
            return true
          }

          this.router.navigate(['/'])
          return false
        })
      )
  }
}

This is method from the service, which return Observable:

  public getUserRoles(): Observable<any> {
    return this.store.pipe(
      select('user'),
      map(({ roles }) => roles)
    )
  }

And this is works when I navigate between page, but when I directly enter in URL some route, for example 'myapp.com/admin', it returns false automatically and the guard does not work. How to make it work properly?

Upvotes: 0

Views: 739

Answers (1)

James World
James World

Reputation: 29786

Best guess, when entering the url directly in the browser, you are restarting your application and the store is reset to defaults with no user.

You should rewrite your getUserRoles() method to check if the user has been authenticated before reading roles, and not just read store state. If you are using OAuth2, for example, this would redirect the user to your authentication endpoint passing appropriate state to resume on the myapp.com/admin route once re-authentication handshake is complete and the store is populated.

The specifics of this will very much depend on what authentication approach you are using.

Upvotes: 1

Related Questions