1
votes

I am running an Angular 9 Universal application that uses NgRx for state management. I am also using ngrx-store-localstorage to persist the Store into the user's localStorage.

I am trying to check if user is loggedIn before accessing certain routes with NgRx inside a Guard:

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

    if (isPlatformBrowser(this.platformId)) {
      console.log('browser')
      return this.store.select('user').pipe(
        map(authUser => {
          if (!authUser.id || !authUser.token) {
            console.log(authUser)
            this.router.navigate(['/login'])
            return false
          }
          return authUser.id ? true : false;
        }))
    }
    console.log('server')
    this.router.navigate(['/login'])
    return false
  }

I am doing a platform check since my server does not have access to the store. But this creates unwanted behaviors since it checks twice and sometimes render the login page before rendering the guarded page.

Do you know a way to let my server know about the current State or an alternative way to verify if my user is authenticated?

1
Just to clarify, there is a summoning in the constructor of private store: Store and there is an @Injectable annotation just above the export, please confirmshuk
Yes sure! Everything is there, and I do have the console.log printed on the browser / server.Simon Brami
I am currently thinking about setting up a cookie on my front end for my jwt. I think the express-engine will have access to that value.Simon Brami
maybe you should give it a go nonetheless, but I doubt that the implementation (which seems ok) of the store is the root cause here, for the reason a 'ssr double render' search on google would yield much to considershuk

1 Answers

1
votes

I ended up using ngx-cookie plugin that makes my guard able to access cookies on the Browser and on the Server: https://github.com/ngx-utils/cookies#servermodulets

My guard looks like that now:

    canActivate(
        next: ActivatedRouteSnapshot,
        state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
        if (isPlatformBrowser(this.platformId)) {
          var token = this.cookies.getObject('_avoSession')
          if (!token) {
            this.router.navigate(['/login'])
            return false
          }
          console.log(token)
          return true

        }
        if (isPlatformServer(this.platformId)) {
          let cookie = this.cookies.getObject('_avoSession')
          if (!cookie) {
            this.router.navigate(['/login'])
            return false
          }
          return true 
        }

  }

The platformCheck here is useless since both my server and browser have access to cookies, but if you need some modularity and add specific checks for different use cases, it can be useful.

You can also verify your jwt by following this example here with Observables.