Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

API call in canactivate method in Angular

Tags:

angular

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.

like image 601
helloworld Avatar asked Nov 17 '18 15:11

helloworld


People also ask

What is canActivate method in angular?

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.

What is canActivate AuthGuard in angular?

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.

What does the canActivate () method return when configuring guards in angular?

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.

What is the difference between canActivate and CanDeactivate in angular?

CanActivateChild - Decides if children routes of a route can be activated. CanDeactivate - Decides if a route can be deactivated.


2 Answers

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);
            }
        );
    });
}
like image 97
Adrita Sharma Avatar answered Sep 25 '22 12:09

Adrita Sharma


You can achieve it like this:

Angular <= 7.0.0

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);
    }),
  );
}

Angular >= 7.1.0

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("/")),
  );
}
like image 22
Ingo Bürk Avatar answered Sep 24 '22 12:09

Ingo Bürk