Handling Guards with redirections, callbacks and unknown paths

738 views Asked by At

For a project, I have a Router with those available paths :

const appRoutes: Routes = [
  {path: '', component: AppComponent},
  {path: 'dashboard', component: DashboardComponent},
  {path: 'leaderboard', component: LeaderboardComponent},
  {path: 'authentication', component: AuthenticationComponent},
  {path: '**', redirectTo: '/authentication', pathMatch: 'full}
];

The Injectable Service of the AuthenticationComponent was handling the router. The user if not authentified would be redirected to /authentication, whatever the route was, and to /dashboard if he's logged in.

The problem is if I want to reload the /leaderboard page, it redirects to /dashboard everytime, and it shouldnt be The Authentication Service's job as well.

I've tried, using This guide to understand guards, which allowed me to handle basic navigation throught the /dashboard and /leaderboard, the callback of Auth0 and the refresh as well, but when accessing my login page while being already authentified, it is not redirecting, same behavior with unknown paths.

Is there a way for me to check if the provided route is known by my Router, and redirect correctly if the user is logged in or not ?

My Guard :

import {ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot} from '@angular/router';
import {AuthenticationService} from './component/authentification/authentication.service';
import {Injectable} from '@angular/core';

@Injectable()
export class AuthGuard implements CanActivate {
  constructor(private authService: AuthenticationService,
              private router: Router) {
  }

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    console.log(route, state);
    this.authService.handleAuthentication();
    if (this.authService.isAuthenticated()) {
      return (true);
    } else {
      this.router.navigate(['/authentication']);
    }
  }
}

My current router :

import {NgModule} from '@angular/core';
import {RouterModule, Routes} from '@angular/router';

import {DashboardComponent} from './component/dashboard/dashboard.component';
import {LeaderboardComponent} from './component/leaderboard/leaderboard.component';
import {AuthenticationComponent} from './component/authentification/authentication.component';
import {AppComponent} from './app.component';
import {AuthGuard} from "./app-routing.guard";

const appRoutes: Routes = [
  {path: '', canActivate: [AuthGuard], redirectTo: '/dashboard', pathMatch: 'full'},
  {path: 'dashboard', canActivate: [AuthGuard], component: DashboardComponent},
  {path: 'leaderboard', canActivate: [AuthGuard], component: LeaderboardComponent},
  {path: 'authentication', component: AuthenticationComponent},
  {path: '**', canActivate: [AuthGuard], redirectTo: '/authentication'}
];

@NgModule({
  imports: [
    RouterModule.forRoot(
      appRoutes
    )
  ],
  exports: [
    RouterModule
  ]
})

export class AppRoutingModule {
}
2

There are 2 answers

0
Quentin Laillé On BEST ANSWER

I went too deep, I only needed to add more verifications in my guard :

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
  this.authService.handleAuthentication();
  if (this.authService.isAuthenticated()) {
    if (state.url === '/authentication') {
      this.router.navigate(['/dashboard']);
    } else {
      return (true);
    }
  } else if (state.url === '/authentication') {
    return (true);
  } else {
    this.router.navigate(['/authentication']);
  }
}
3
Yakov Fain On

If your goal is to check if the provided route is known to the Router, use RoutesRecognized event:

export class AppComponent {

  constructor (private router: Router){
    this.router.events.subscribe(
      (event) => this.handleRouterEvents(event)
    );
  }

  handleRouterEvents(event){
    if (event instanceof RoutesRecognized){
      console.log("The user provided the known route");
    } else{
      console.log("The user provided unknown route");
    }
  }

If you need the URL of the route, check the Router.url property. Turn on the tracing and check the output on the console:

export const routing = RouterModule.forRoot(routes,
  { enableTracing: true });