I need to implement a CanActivateFn guard to block non authenticated users in an Angular project.
I tried different approaches and shaped this guard so far.
import { inject } from '@angular/core';
import {
ActivatedRouteSnapshot,
CanActivateFn,
Router,
RouterStateSnapshot,
UrlTree,
} from '@angular/router';
import { IUser } from '../model/user.model';
export const authGuard: CanActivateFn = (
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Promise<boolean | UrlTree> | boolean | UrlTree => {
let isAuthenticated = false;
let baseUrl: string = 'https://localhost:44411/';
let currentUser = <IUser>{};
// I need to get user info syncronusly
fetch(baseUrl + 'Account/GetUser')
.then((response) => response.json())
.then((json) => {
currentUser = jsonas IUser;
})
.catch((error) => {
console.error('There was an error to get user information.');
});
isAuthenticated = currentUser.isAuthenticated;
// 👇 Redirects to login route
const isAnonymous = !isAuthenticated;
if (isAnonymous) {
return inject(Router).createUrlTree(['/', 'login']);
}
return isAuthenticated;
};
The issue is that I need to find a way to get user data synchronously to be able to do validation based on a user data.
Please suggest how to achieve the requirement or suggest a different approach. Note: I need to use fetch to get user data.
Convert the promise to an observable, then validate the logic on a map
if error catch using catchError
present then navigate.
import { inject } from '@angular/core';
import {
ActivatedRouteSnapshot,
CanActivateFn,
Router,
RouterStateSnapshot,
UrlTree,
} from '@angular/router';
import { IUser } from '../model/user.model';
import { lastValueFrom } from 'rxjs';
import { map, catchError } from 'rxjs/operators';
import { HttpClient } from '@angular/common/http';
export const authGuard: CanActivateFn = (
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Promise<boolean | UrlTree> | boolean | UrlTree => {
let baseUrl: string = 'https://localhost:44411/';
// I need to get user info syncronusly
return lastValueFrom(
inject(HttpClient).get(baseUrl + 'Account/GetUser')
).pipe(
map((currentUser: any) => {
return !currentUser.isAuthenticated
? inject(Router).navigate(['login'])
: false;
}),
catchError(() => inject(Router).navigate(['login']))
);
};
using fetch
import { inject } from '@angular/core';
import {
ActivatedRouteSnapshot,
CanActivateFn,
Router,
RouterStateSnapshot,
UrlTree,
} from '@angular/router';
import { IUser } from '../model/user.model';
import { lastValueFrom } from 'rxjs';
import { map, catchError } from 'rxjs/operators';
import { HttpClient } from '@angular/common/http';
export const authGuard: CanActivateFn = (
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Promise<boolean | UrlTree> | boolean | UrlTree => {
let baseUrl: string = 'https://localhost:44411/';
// I need to get user info syncronusly
return lastValueFrom(fetch(baseUrl + 'Account/GetUser')
.then((response) => response.json())).pipe(
map((currentUser: any) => {
return !currentUser.isAuthenticated
? inject(Router).navigate(['login'])
: false;
}),
catchError(() => inject(Router).navigate(['login']))
);
};