2

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?

Simon Brami
  • 159
  • 1
  • 10
  • 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 confirm – shuk Jun 16 '20 at 18:44
  • Yes sure! Everything is there, and I do have the console.log printed on the browser / server. – Simon Brami Jun 16 '20 at 18:48
  • 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 Jun 16 '20 at 19:09
  • 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 consider – shuk Jun 16 '20 at 19:21

1 Answers1

2

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.

Simon Brami
  • 159
  • 1
  • 10
  • Since you are using `ngx-cookie` which supports SSR, you don't even need the platform check (you've basically got twice the same code above) – David Jun 18 '20 at 08:12
  • Yes I've mentioned that just bellow ;) – Simon Brami Jun 18 '20 at 19:01
  • Oh sorry I missed that! – David Jun 18 '20 at 19:57
  • @Simon Brami could you please explain what(in which files) and how(steps) you made the changes? do we need to make changes in server.ts file also? what is '_avoSession' in your case, where do you set that? pls help by explaining more on your solution, – ganesh Jun 28 '22 at 17:53