After searching extensively, I was unable to find a question that directly addresses my specific concern. Currently, I am working on a project involving an angular application that utilizes jwt and http-only cookies for authentication. In order to authenticate requests on the backend, the jwt cookie is sent with each request. While everything is functioning properly, I am curious about the most effective method for verifying user authentication - particularly the WHERE.
From my research, it seems that the common approach involves using AuthGuards and a custom AuthService to validate Authentication and secure routes. In my case, I can verify authentication by utilizing an endpoint /api/users/currentuser
which is solely dedicated to checking the jwt token and responding with a user object if the user is authenticated. This method works well, but I am uncertain about the optimal location within an angular application to trigger this request.
Should I place the request in the
constructor
of my AuthService, ensuring it is the first operation executed and then set aBehaviorSubject<boolean>
that other components can subscribe to?export class AuthService { isLoggedIn$ = new BehaviorSubject < boolean > (this.isLoggedIn); ... constructor() { // initiate call to /api/users/currentuser backend // set isLoggedin$ to true/false based on currentuser response this.isLoggedIn$.next(value); }
Should the AuthGuard responsible for protecting one or more routes perform its own request to the backend within
canActivate
method?canActivate( route: ActivatedRouteSnapshot, state: RouterStateSnapshot ): | Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree { if (!this.authService.getCurrentUser()) { console.log('NOT authenticated'); this.router.navigate(['']); return false; } console.log('AUTHENTICATED'); return true; }
Or should the AuthGuard subscribe to the AuthService BehaviorSubject like this:
canActivate( route: ActivatedRouteSnapshot, state: RouterStateSnapshot ): | Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree { if (!this.authService.isLoggedIn$.getValue()) { console.log('auth guard NOT authenticated'); this.router.navigate(['']); return false; } console.log('AUTHENTICATED'); return true; }
Should the call to
/api/users/currentuser
be executed usingasync ... await ...
at the beginning of the page load to ensure authentication is verified before the page is rendered?Particularly after a page refresh - where is the ideal location for the authentication process to occur?
Is there a definitive location within the application where a single call to /api/users/currentuser
should occur? Should this call be made multiple times from various places (authservice, authguard, different components, etc) for security reasons or is there a more efficient approach to sharing the authentication status among components?
Current app.component.html:
<app-navbar></app-navbar>
<router-outlet></router-outlet>