1
votes

I'm currently working with authentication and authorization. Authentication and Authorization works perfectly. I've 3 roles: Admin, Doctor, User.

When admin is logged in admin can go to Admin Dashboard and not User or Doctor dashboard. Similarly each role can access their specific dashboard.

What I want to achieve is to automatically re-direct users to their dashboard based on their role. For Example (pseudocode):

if user.role = "Admin", this.router.navigate["/adminlogin"];

if user.role = "Doctor", this.router.navigate["/doctorlogin"];

if user.role = "User", this.router.navigate["/udashboard"];

How can I achieve this and where do I add the if condition? Any code will be highly appreciated.

My Code is as follows:

AuthGuard.ts:

 canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    const currentUser = this.authenticationService.currentUserValue;

    if (currentUser) {
        // check if route is restricted by role
        if (route.data.roles && route.data.roles.indexOf(currentUser.role) === "-1") {
            // role not authorised so redirect to home page
            this.router.navigate(['/']);
            return false;
        }
        // authorised so return true
        return true;

    }

    // not logged in so redirect to login page with the return url
    this.router.navigate(['/login'], { queryParams: { returnUrl: state.url }});
    return false;
}

canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
  const currentUser = this.authenticationService.currentUserValue;
  if (currentUser) {
      // check if route is restricted by role
      if (route.data.roles && route.data.roles.indexOf(currentUser.role) === -1) {
          // role not authorised so redirect to home page
          this.router.navigate(['/']);
          console.log("NOT RUNNING CHILD ACTIVATE");
          return false;

      }

      // authorised so return true
      console.log("CAN-ACTIVATE-CHILD RUNNING")
      return true;
  }

  // not logged in so redirect to login page with the return url
  this.router.navigate(['/login'], { queryParams: { returnUrl: state.url }});
  return false;
}

Login.Component.ts

  // get return url from route parameters or default to '/'
 this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/';

}


// convenience getter for easy access to form fields
get f() { return this.loginForm.controls; }

onSubmit() {
    this.submitted = true;

    // stop here if form is invalid
    if (this.loginForm.invalid) {
        return;
    }

    this.loading = true;
    this.authenticationService.login(this.f.username.value, this.f.password.value)
        .pipe(first())
        .subscribe(
            data => {

                this.router.navigate([this.returnUrl]);
            },
            error => {
                this.error = error;
                this.loading = false;
            });
}

app-routing.module.ts

 {      path:'', 
        component: BackendLayoutComponent, 
        canActivateChild: [AuthGuard],
        data: { roles: [Role.User] },
        children: 
        [
            { path:'udashboard', component: DashboardComponent,  
            data: { roles: [Role.User] } },

            { path:'doctors', component: DoctorsComponent,  
            data: { roles: [Role.User] } },
        ],
    },
    {   path:'', 
        component: DocBackendLayoutComponent,
        canActivateChild: [AuthGuard],
        data: { roles: [Role.Doctor]},
        children: 
        [ { path:'doctorlogin', component: DoctorDashboardComponent,
            data: { roles: [Role.Doctor]} },

            { path:'doctorprofile', component: DocProfileComponent,
            data: { roles: [Role.Doctor]} },
        ]
    },
    {   path:'', 
        component: AdminBackendLayoutComponent,
        canActivateChild: [AuthGuard],
       data: { roles: [Role.Admin]},
        children: 
        [
            { path:'adminlogin', component: AdminDashboardComponent,
            data: { roles: [Role.Admin]} },

            { path:'clinicrequests', component:ClinicRequestsComponent,
            data: { roles: [Role.Admin]}},
        ]
    },

Thank you.

2
So the only thing you want is to redirect to /udashboard if role = User, /doctorprofile if role = doctor etc ?Joniras
Yes, that's exactly what I want.String Name

2 Answers

3
votes

You need to implement RoleGuard along with AuthGuard. Use AuthGuard only for Authorization. An example is following Hope it will help you. In my case I use RoleGuard after login. After login user is redirected to MainMenu and then further redirected to respective dashboard according to role.

Note: It is not exact solution of your scenario you need to implement it according to your needs.

RoleGuard Service.ts

@Injectable()
export class RoleGuard implements CanActivate {

  constructor(private _auth: AuthService,
    private _router: Router) { }

  canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
    const expectedRole = route.data.expectedRole
    if (this._auth.isLoggedIn() && expectedRole == this._auth.getUserRole()) {
      return true;
    } else {
      this._router.navigate([RouterLinkEnum.USER_LOGIN]);
      return false;
    }
  }

MainMenu module routes . They will work after login. Note I am sending Role to RoleGuard with route

const routes: Routes = [
    { path: 'vendor',
                loadChildren: 'app/admin-panel/vendor/vendor.module#VendorModule',
                canActivate: [RoleGuard],
                data: {
                    expectedRole: ExpectedRoleEnum.ADMIN
                }

            }
];
0
votes

try the following

login.component.ts

//....

onSubmit() {
    this.submitted = true;

    // stop here if form is invalid
    if (this.loginForm.invalid) {
      return;
    }

    this.loading = true;
    this.authenticationService.login(this.f.username.value, this.f.password.value)
      .pipe(first())
      .subscribe(
        data => {
          this.redirectUser(data.role);
        },
        error => {
          this.error = error;
          this.loading = false;
        });
  }

redirectUser(userRole) {
    if (userRole == Role.User) {
      this.router.navigate(['/user']);
    } else if (userRole == Role.Guest) {
      this.router.navigate(['/guest']);
    } else if (userRole == Role.Admin) {
      this.router.navigate(['/admin'])
    }
}

app-routing.module.ts

//...
const routes: Routes = [
  { path: 'login', component: LoginComponent },
  { path: 'user', component: BoUserComponent, canActivate: [AuthGuard], data: { roles: [Role.User] } },
  { path: 'guest', component: GuestComponent, canActivate: [AuthGuard], data: { roles: [Role.Guest] } },
  { path: 'admin', component: AdminComponent, canActivate: [AuthGuard], data: { roles: [Role.Admin] } },

  // otherwise redirect to home
  { path: '**', redirectTo: 'login' }
];

auth.guard.ts

//...
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    const currentUser = this.authenticationService.currentUserValue;
    if (currentUser) {
      // check if route is restricted by role
      if (route.data.roles && route.data.roles.indexOf(currentUser.role) === -1) {
        // role not authorised so redirect to home page
        this.authenticationService.logout();
        this.router.navigate(['/login']);
        return false;
      }
      // logged in so return true
      return true;
    }

    // not logged in so redirect to login page with the return url
    this.router.navigate(['/login'], { queryParams: { returnUrl: state.url } });
    return false;
  }