-1

I am currently building a route guard that checks if my client is authenticated. Since I am using http only cookies I have to send a request to my server which then returns if the cookie is valid or not. This is the code for my guard:

export class AuthGuard implements CanActivate {
  constructor (private auth: AuthService){}
  
  async canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Promise<boolean> {

      let isAuthenticated : boolean = false;
      
      await this.auth.getAuthStatus().subscribe(
        res => {
          if(res.status == 200){
            isAuthenticated = true;
          }
      })
      console.log(isAuthenticated)
      return isAuthenticated;
  }
}

and the service is just a simple http call:

  getAuthStatus(): Observable<HttpResponse<any>>{
    return this.http.post(environment.server + environment.routes.authRoutes.status, "", {
      withCredentials: true,
      observe: 'response'
    })
  }

The problem I am facing is that my guard has to return a boolean for the router, and since I am using .subscribe it returns false since it returns siAuthenticated before I .subscribe finishes. I tried adding await and returning a promise, but either it does not work in my case or I did not use it correctly. I tried finding a solution in different posts, but none of them worked for me (Or I just didnt understand them properly and implemented them in the wrong way).

Thank you

Kleecarim
  • 117
  • 1
  • 1
  • 7

2 Answers2

1

await needs a Promise So you can use toPromise() method of Observable and change the return type of getAuthStatus().

But as @ShamPooSham mentioned in the comment, I also recommend returning Observable instead of a Promise from the guard.

getAuthStatus(): Promise<HttpResponse<any>>{
    return this.http.post(environment.server + environment.routes.authRoutes.status, "", {
      withCredentials: true,
      observe: 'response'
    }).toPromise()
  }


await this.auth.getAuthStatus().then(res => {...})
Harun Yilmaz
  • 8,281
  • 3
  • 24
  • 35
  • Thank you, I will implement it and mark your question as solved if it works. Do you mind explaining why an observable would be better than a promise in this case? – Kleecarim Oct 13 '21 at 07:50
  • Sure. It's a choice of how you want your app to be. I personally prefer observables to make the app more reactive rather than waiting for a promise to return a value which, I think, is against the async pattern. It helps avoiding the callback mess. And I find it more intuitive and more readable. – Harun Yilmaz Oct 13 '21 at 07:56
1

for newer RxJS version you can write

const response = await lastValueFrom(this.auth.getAuthStatus());

and for older

const response = await this.auth.getAuthStatus().toPromise();
  • I treid to import { lastValueFrom } from 'rxjs' but apparently rxjs 'does not have the exportet member' – Kleecarim Oct 13 '21 at 08:31