my Test
my Test

Reputation: 105

Angular routing based on roles

I am using Angular and this is for my authentication check:

export class EnsureAuthenticated implements CanActivate {
    constructor(private auth: AuthService, private router: Router) {}
    canActivate(): boolean {
        if (localStorage.getItem('token')) {
            return true;
        }
        else {
            this.router.navigateByUrl('/login');
            return false;
        }
    }
}    

{ 
    path: 'path', 
    component: myComponent,
    canActivate: [EnsureAuthenticated]
}

It's working fine but my problem is this page can be accessed by both user and admin.

I know I didn't set any condition on it. How do I set the proper condition on it?

I don't want to access this page to admin

Upvotes: 2

Views: 7478

Answers (3)

dasunse
dasunse

Reputation: 3089

See this example in stackblitz

In your app-routing.module.ts

const routes: Routes = [
   {
       path: "admin",
       component: AdminOnlyComponent,
       canActivate: [RoleGuardService],
       data: { roles: ['admin']}
   },
   ...
}

In your RoleGuardService

import { Injectable } from '@angular/core';
import { UserRolesService} from './user-roles.service';
import { Router, ActivatedRouteSnapshot } from '@angular/router';
@Injectable({
  providedIn: 'root'
})
export class RoleGuardService {

  constructor(private getUserRoles: UserRolesService) { }

  canActivate(route: ActivatedRouteSnapshot): boolean {
    return route.data.roles.some( ai => this.getUserRoles.getRoles().includes(ai) );
  }
}

In UserRolesService

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class UserRolesService {
   userRoles: string[] = [];

  constructor() { }

  setRoles(Roles: string[]){
    this.userRoles = Roles.slice(0);
  }

  getRoles(){
    return this.userRoles;
  }
}

Set roles when user logged in to the system or get those roles from your localstorage....

Upvotes: 5

Robert
Robert

Reputation: 564

You should create a RoleGuardService, that expect a role from a user and check if this role is equal of the role espected, like this:

  constructor(public auth: AuthService, public router: Router) {}

  canActivate(route: ActivatedRouteSnapshot): boolean {

    // this will be passed from the route config
    // on the data property
    const expectedRole = route.data.expectedRole;

    const token = localStorage.getItem('token');

    // decode the token to get its payload
    const tokenPayload = decode(token);

    if (
      !this.auth.isAuthenticated() || 
      tokenPayload.role !== expectedRole
    ) {
      this.router.navigate(['login']);
      return false;
    }
    return true;
  } 

And protect yout routing by user roles guard like:

{ 
    path: 'admin', 
    component: AdminComponent, 
    canActivate: [RoleGuard], 
    data: { 
      expectedRole: 'admin'
    } 
  }, 

This scenario assumes that you are using a custom role claim in your JWT, for further information i advice you to read that article that explain perfectly your answer: https://medium.com/@ryanchenkie_40935/angular-authentication-using-route-guards-bf7a4ca13ae3

Upvotes: 0

JoH
JoH

Reputation: 554

Assuming that you have a service to retrieve the connected user's role, you just have to check that role and return false if the user is an admin to prevent that kind of users to have access to your pages. If the token you store in the lcoal storage is a JWT token, sometimes the user role is encoded into it, you have to decode the token to extract the role.

Upvotes: 0

Related Questions