I have an observable to check if the user is loggedIn or not. I set that observable from auth api which is called from appComponent when application starts.
export class AppComponent implements OnInit {
loggedIn$: Observable<boolean | null>;
constructor(private userService:UserService) {
this.userService.authenticate();
}
ngOnInit(): void {
//to show header when loggedin
this.loggedIn$ = this.userService.isAuthenticated;
}
}
and I have AuthGaurd which restricts unauthenticated users from navigating to inner pages.
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | UrlTree | Observable<boolean | UrlTree> | Promise<boolean | UrlTree> {
return this.userService.isAuthenticated.pipe(
take(1),
map((loggedin:boolean) => {
if(loggedin) {
//checking for required permissions as well
let permission = route.data['permission'];
if( this.userService.hasPermission(permission)) {
return true;
}
}
this.router.navigate(['unauthorised-user', { page: state.url}]);
return false;
})
);
}
and here's aut service
private loggedIn: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
public authenticate() {
this.http.get<User>('<auth-api-url')
.subscribe(
(response: user) => {
this.user = response;
if (this.user) {
document.cookie = `coockie`;
this.loggedIn.next(true);
this.getReferenceData();
}else {
this.loggedIn.next(false);
}
}
);
}
get isAuthenticated(): Observable<boolean> {
return this.loggedIn.asObservable();
}
public hasPermission(permission:string): boolean {
return this.user?.permissions?.includes(permission);
}
when I launch the app "/" appComponent makes call to auth api but auth guard checks and redirects user to unauthorised-user page as auth api hasn't finished yet.
I have looked at few solutions which adds auth api call into canActivate guard but then it calls api every time I navigate to different page. I would like to call the api once and then set the flag (observable) in auth service which other components can use to check if user is authenticated or not.
Thanks
The current implementation will always deceive you as app.component.ts is not the right entry point to place your authentication code. app.module.ts is the root point to place the authentication logic.
],
Here, contextPopulate is the method that calls the auth endpoint each time your app refreshes/restarts/starts. It will not proceed until receive a response from the promise(either authorized or unauthorized).
Remove the code from app.component.ts. app.module.ts and auth method from userService is all you need to implement authentication.