7
votes

I used login-guard for some routes (e.g. '/profile'). Looks like this:

canActivate() {
    if (this.user.islogin) return true;
    this.router.navigate(['']);
}

It redirects user to main page if he's not logged in and tries to get access to some routes. It works fine. User can log out from any page. I want my app to have next behavior: If user is on '/profile' page and clicks 'logout', he should be redirected to main page by canActivate() method. But this method isn't called in this case. What should I do to run canActivate()(reload page, manually call)? My logout method:

logout() {
    localStorage.removeItem('auth_token');
    this.islogin = false;
}

I've tried to add this.router.navigate([this.router.url]); to logout method, but result is the same. Only if I reload page, angular2 redirects me. What is the right way?

3

3 Answers

8
votes

Considering that your guard just uses islogin and that you're setting this to false when the user logs out, the easiest way is to simply redirect upon logout:

logout() {
    localStorage.removeItem('auth_token');
    this.islogin = false;
    this.router.navigate(['']);    <---- ADD THIS
}

If you want to reuse the logic in canActivate() without changing route first, you could do it like this:

First, inject the services wherever your logout() is:

constructor(
    private router: Router,
    private route: ActivatedRoute,
    private canActivateGuard: CanActivateGuard) {}

(Just use the name you used instead of CanActivateGuard)

Next, call it in logout():

logout() {
    this.canActivateGuard.canActivate(
        this.route.snapshot,
        this.router.routerState.snapshot);
}
8
votes

The question is old, but the problem is current.

From Angular v6 you can set the onSameUrlNavigation property of the router:

RouterModule.forRoot(routes, {
    ...
    onSameUrlNavigation: 'reload'
})

and set runGuardsAndResolvers where do you need:

{
    path: '',
    component: AccountComponent,
    canActivate: [AuthGuard],
    runGuardsAndResolvers: 'always'
}

In your logout method, just call the same route, and the canActivate method of your auth guard will be fired:

signout(): void {
    this.store.dispatch({
        type: AuthActionTypes.Signout
    });
    // Navigate to the same url to invoke canActivate method
    // in routes with runGuardsAndResolvers.
    // Also activated onSameUrlNavigation router property.
    this.router.navigate([this.auth.redirectUrl]);
}

In the sample above, redirectUrl is a property where the current url is saved.

0
votes

Though an old question I encountered similar issue and I solved it simply by using async and await

I am using Firebase Authentication with Angular using AngularFireAuth

When I use the following code:

  logout(){
    this.fbAuthService.fbSignOut();
    this.router.navigate(['/login']);
  }

the user is properly signed out but this.router.navigate(['/login']) does no work! It works if I reload the page.

Later I suspected that I may have to wait for the signout process to complete and then call this.router.navigate(['/login'])) function.

So I changed it to:

  async logout(){
    await this.fbAuthService.fbSignOut();
    this.router.navigate(['/login']);
  }

And it works like a charm! Hope it helps someone who might stumble upon this.