Reputation: 202
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.
Upvotes: 1
Views: 8667
Reputation: 1067
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
}
}
];
Upvotes: 3
Reputation: 501
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;
}
Upvotes: 0