my router is not working properly, when I go to the pageNotFound page and want to go back to previous steps, it redirects me to the login page, I would be grateful for any tips on how to fix it. Debuilding shows that the method in authenticationguard - canActive() returns false when returning from this page, unfortunately I cannot find out why the user is not read correctly
export const routes: Routes = [
{
path: 'forbidden',
component: ForbiddenPageComponent,
},
{
path: 'auth',
loadChildren: () => import('./modules/auth/auth.module').then(mod => mod.AuthModule),
component: AuthComponent,
},
{
path: '',
canActivate: [AuthenticationGuard],
canActivateChild: [AuthorizationGuard],
children: [
{
path: 'task',
loadChildren: () => import('./modules/task/task.module').then(mod => mod.TaskModule),
},
{
path: 'order',
loadChildren: () => import('./modules/order/order.module').then(mod => mod.OrderModule),
},
{
path: '',
pathMatch: 'full',
redirectTo: 'task',
}
],
},
{
path: '**',
pathMatch: 'full',
component: PageNotFoundComponent
}
];
@Injectable({
providedIn: 'root',
})
export class AuthenticationGuard {
currentUser: OPLUser | null;
constructor(
private authService: AuthService,
private router: Router,
@Inject(APP_CONFIG) private appConfig: AppEnvConfiguration
) {
this.authService.currentUser$.subscribe(user => {
this.currentUser = user;
});
}
canActivate(): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
if (this.appConfig.skipLogin || (this.currentUser && this.currentUser.isAuthenticated())) {
return true;
}
this.router.navigate(['/auth'], { replaceUrl: true });
return false;
}
}
@Injectable({
providedIn: 'root',
})
export class AuthorizationGuard {
constructor(
private authService: AuthService,
private router: Router,
@Inject(APP_CONFIG) private appConfig: AppEnvConfiguration
) {}
/**
* Checks if user is authorized to activate this route.
* If not, user is redirected to 'forbidden' page.
*
* @param route
*/
canActivateChild(
route: ActivatedRouteSnapshot
): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
const currentUser = this.authService.currentUser$.getValue();
if (currentUser && currentUser.authenticatedAndAuthorized) {
if (this.appConfig.skipLogin) return true;
const routeRoleList: RouteRule = route && route.data ? route.data['roleList'] : null;
if (!routeRoleList || this.matchesRole(routeRoleList, currentUser)) {
return true;
} else {
this.router.navigate(['forbidden'], { skipLocationChange: true });
return false;
}
} else {
this.router.navigate(['forbidden'], { skipLocationChange: true });
return false;
}
}
/**
* Checks if user roles matches route role configuration.
* OneOf - checks any role.
* AllOf - checks all roles.
*
* @param routeRoleList - provided route role configuration.
* @param user - current user.
*/
matchesRole(routeRoleList: RouteRule, user: OPLUser | null): boolean {
let match = true;
if (routeRoleList.oneOf && routeRoleList.oneOf.length > 0) {
match = routeRoleList.oneOf.some(role => user?.hasRole(role));
}
if (routeRoleList.allOf && routeRoleList.allOf.length > 0) {
match = routeRoleList.oneOf.every(role => user?.hasRole(role));
}
return match;
}
}
This is happening due to the order in which you have configured your routes. The Angular router will go in order evaluating the path you define in your route config object against the current url. What's happening here is the router is encountering your empty path with the children and that matches the url (because you don't have
pathMatch: fullon that one). It then tries to route you to/taskbased on the redirect there, which is protected by theAuthenticationGuard, so you get redirected to login.You can fix this by adding
pathMatch: fullto the empty path like this:If you want to debug the router yourself, you can do that by enabling router tracing. It will log the processes the router goes through to the console. You can do that by adding the option in your root level app-routing.module.ts like this:
If you're using a standalone angular app (which bootstraps your Angular app with the
bootstrapApplicationmethod, you can enable router tracing by including thewithDebugTracingfrom the@angular/routerlike this: