4

I have an application where there are two guards (MsalGuard - for Authentication, AuthGuard - written own code to authorize whether the user is having access to that particular page). Using the lazyloading while loading the modules. Please find the below-mentioned code

app-routing.module.ts

      { 
        path: 'administration',
        loadChildren: () => import('./administration/administration.module').then(m => 
        m.AdministrationModule),
       // loadChildren: './administration/administration.module#AdministrationModule',
       canActivate: [MsalGuard],
      },

administration-routing.module.ts

           path: '',
    //canActivate: [AuthGuard],
    component: AdministrationComponent,

       children: [
         {
           path: 'user-admin/user-list',
           children: [
              { path: '', component: UserListComponent, canActivate: [AuthGuard] },
              { path: 'user-creation', component: UserCreationComponent, canActivate: [AuthGuard] },
           ]
         },

auth.guard.ts

     canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
        const currentUser = this.authenticationService.currentUserValue;
        if (currentUser) {
            return this.hasAdminAccess(state, currentUser);
        } 
        this.router.navigate(['/login'], { queryParams: { returnUrl: state.url } });
        return false;
    }

Here the main issue it is working as expected if we logged once and able to authorize accordingly.. but in case If I cleared the total cache and opening one of the component page directly then it is asking MsalAuth and providing the details but by that time AuthGuard might be executed and user details are empty and it is opening the page without authorization.

Khan Saad
  • 823
  • 1
  • 9
  • 26

1 Answers1

0

I solved it finally by checking the login process in the canactivate of my own guard:

export class UserGuardService {
    
constructor(private userSrv: EmployeeService, private msalBroadcastService: MsalBroadcastService) { }
    
      canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
        return this.msalBroadcastService.inProgress$
        .pipe(
          filter((status: InteractionStatus) => status === InteractionStatus.None)
          )
        .pipe(() => {
          //Getting the user from the service, this needs accesstoken first, so msal need to be completed
          return this.userSrv.getUser().pipe(
            filter(user => !!user),  // Filter NULL value here before sending object further
            map(user => {
              let hasRights = true;
              //Check on roles
              return hasRights;
            }));
        });
      }
    }

So then you are sure its called after the login process completes!

Mark
  • 379
  • 3
  • 7
  • Thanks for the reply Mark. I have one small doubt related to this. If we implement the Login implementation in CanActivate then the lazy loaded modules (API calls) will be loaded before knowing whether the USER is authorized to that particular module or not. We need to CalLoad method to implement the same Might be as in back ground unnecessarily lazy loading components will be loaded? – Karthik Myakala Dec 16 '21 at 13:45