Role management in Angular 4+ routes (JWT)

1

I would like to know what is the best way to handle user roles in Angular?

The scenario is as follows: I have an application in Angular that consumes a REST API made with Laravel, the same one that gives me a token. The application will handle 3 types of roles (administrator, student, teacher), the routes are protected by a Guard service

  { path: '', redirectTo: 'login', pathMatch: 'full' },
  { path: 'login', component: LoginComponent },
  {
    path: 'admin', component: DashAdminComponent, children: [
      {
        path: 'estudiantes', component: EstudiantesComponent, children: [
          { path: 'nuevo-estudiante', component: NuevoEstudianteComponent, canActivate: [GuardService] },
          { path: 'todos', component: ListaComponent, canActivate: [GuardService] },
          { path: 'editar/:id', component: EditarComponent, canActivate: [GuardService],  }
        ], canActivate: [GuardService]
      },
      { path: 'docentes', component: DocentesComponent, children:[
        { path: 'nuevo-docente', component: NuevoDocenteComponent, canActivate: [GuardService] },
        { path: 'lista-docente', component: ListaDocenteComponent, canActivate: [GuardService] },

      ], canActivate: [GuardService] }


    ], canActivate: [GuardService]
  },

The Guard service verifies if the token is present and valid

  canActivate() {
    if (this.apiSerive.getLogged()) {
      return true;
    } else {
      this._router.navigate(['/login']);
      return false;
    }
  }

However, this logic (checking if the token is valid and present) could allow a user with a student role to access a route intended for administrator role users. >.

Any suggestions are welcome.

    
asked by Joel Muñoz Moran 08.08.2018 в 07:07
source

1 answer

1

If you provide the user's privileges together with the user data when the API authorizes you, you can do something similar to:

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    let authorization = this.isLoggedIn();
    const privileges = route.data['privileges'];

    if(privileges){
      for(let priv of privileges) {
        authorization = authorization && this.getUser().hasPrivilege(priv);
      }
    }
    if (authorization) { return true ; }
    return false;
  }

  canAccess(privilege){
    return this.getUser().hasPrivilege(privilege);
  }

And in your module, specifically in the routes, something similar to:

canActivate: [AuthService],
data: {privileges: ['administrador'] }

EDITING

Top instacon route as ActivatedRouteSnapshot .

According to the ActivatedRouteSnapshot documentation and more or less understandably translated, it contains information about the route associated with a component loaded at a certain moment. It can also be used to navigate the route state tree.

One of its properties is data that contains the static and resolved data of the loaded route.

In data we can, then, save data that is useful to us , such as privileges , or to be more faithful to your scheme, roles .

For example , above, in my canActivate work with privileges, but you could change all those privileges and call them roles without problem. There is a part where I ask if this.getUser().hasPrivilege(priv); , well, that method I have in my model User (user.ts) and it is something like this:

hasPrivilege(key: string) : boolean{
    if (!this.privileges) { return false; }        
    return this.privileges.filter(p => p.key === key).length > 0;
}

Privilege is a property of my user model that, among other things, has:

export class User {
    id: number = null;
    name: string;
    full_name: string;
    email: string;
    privileges: Array<Privilege> = [];
    password: string;

... What is another model that has:

export class Privilege {
    id: number;
    key: string;
    name: string;
    description: string;
}

As you see, in summary I get my server user , canActivate takes care of asking if the user (which comes with their privileges from the server and I am responsible for instantiating it correctly) has some specific privilege (s) needed for the particular route and returns true or false depending on whether meets the requirements . Those privileges of that particular route that I mention, are the ones that I define in the data property in the route by which you were asking ... basically I am saying, when you ask if the user canActivate, it indicates that this requires (these) privilege (s) / role (s).

    
answered by 08.08.2018 / 07:27
source