I am using canActivate
using guards
in Angular. I want to check if the user is authenticated and based on the result protect the route.
There are two types of users: Type1
and Type2
, so user can be either authenticated with Type1
, Type2
or unauthenticated
.
The following guard
is for Type1
user.
Here is my code:
constructor(private authservice: AuthService, private router: Router, private route: ActivatedRoute){}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean{
const self = this;
const expectedType = "type1";
this.authservice.isUserAuthenticatedbyType(expectedType).then(
function(data){
if(data === false){
console.log(data);
self.router.navigate(['/'], {relativeTo: self.route});
}
return data;
},
function(error){
self.router.navigate(['/']);
return false;
}
);
return false;
}
The problem is I make an API call to validate if the user is authenticated and return false;
is executed before the result from the API. So, momentarily I see a different page and then it is routed to the correct page. How can I fix this, I do not want to return false or true before the API call, but not doing that gives an error.
I also tried the following:
return this.authservice.isUserAuthenticatedbyType(expectedType)
But this simply navigates me to the http://localhost:4200
url in case of unauthenticated
user.
I have the following route:
{ path: "", component: HomeComponent },
So, in the above scenario, HomeComponent
should have been called, but ngOnInit
of HomeComponent is not getting called.
CanActivatelinkInterface that a class can implement to be a guard deciding if a route can be activated. If all guards return true , navigation continues. If any guard returns false , navigation is cancelled.
AuthGuard is used to protect the routes from unauthorized access in angular. How AuthGuard Works? Auth guard provide lifecycle event called canActivate. The canActivate is like a constructor. It will be called before accessing the routes.
CanActivate. Guards are implemented as services that need to be provided so we typically create them as @Injectable classes. Guards return either true if the user can access a route or false if they can't.
CanActivateChild - Decides if children routes of a route can be activated. CanDeactivate - Decides if a route can be deactivated.
You can also try like this:
canActivate(): Observable<boolean> | Promise<boolean> | boolean {
return new Promise(res => {
this.authservice.isUserAuthenticatedbyType("type1").subscribe(
(data) => {
if (data === true) {
res(true);
} else {
this.router.navigate(['/']);
res(false);
}
},
(error) => {
this.router.navigate(['/']);
res(false);
}
);
});
}
You can achieve it like this:
public canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
return this.authservice.isUserAuthenticatedbyType("type1").pipe(
map(data => {
if (data === false) {
this.router.navigate(['/']);
return false;
}
return !!data;
}),
catchError(() => {
this.router.navigate(['/']);
return of(false);
}),
);
}
Starting with Angular 7.1.0 (note that it's not in 7.0.x), you can also do this instead, which is shorter and more predictable if you have multiple guards:
public canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
return this.authservice.isUserAuthenticatedbyType("type1").pipe(
map(data => data === false ? this.router.parseUrl("/") : !!data)
catchError(() => this.router.parseUrl("/")),
);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With