node.jsjwtnestjs

NestJS - how to check if JWT can access specific endpoint


Let's say I have 3 endpoints: A is for generating JWT token, B for accessing data of user X and C for accessing data of user Y. Now, what I want to do is, that I can from received token somehow in controller guards figure out, if user can access endpoint.

So, token generated for user X can only access endpoint B, token generated for user Y can only access endpoint C.

Token has to be generated at endpoint A, since users sign in at same form. If question is unclear ask in comment.


Solution

  • You Can do that by specifying in the payload a role, by this role you set a guard on each endpoint which role has the access to it. let me give an example:

    I believe that you have a function where you fill you payload kind of this function :

        createJwtPayload(user){
        let data: JwtPayload = {
            userData: user,
            companyId : user.company.id,
            role:user.role.name, // for us this where we specify the role for our User
        };
    
       ......
    }
    

    Now We have to create guards we need to specify access for x endpoints
    let start with Admin Guard:

        @Injectable()
                export class AdminGuard implements CanActivate {
            async canActivate(context: ExecutionContext): Promise<boolean> {
             const request = context.switchToHttp().getRequest();
       
          if (!request.headers.authorization) {
            return false;
          }
          request.user = await this.validateToken(request.headers.authorization);
           if( request.user.role == ROLES.SUPER_ADMIN) {
              return true;
            }
           return false;
                 }
    
             async validateToken(auth: string) {
                ......
          }  
    

    lets make the second guard we call it EmployeGuard :

     ....
    @Injectable()
    export class EmployeGuard implements CanActivate {
      async canActivate(context: ExecutionContext): Promise<boolean> {
        const request = context.switchToHttp().getRequest();
       
          if (!request.headers.authorization) {
            return false;
          }
          request.user = await this.validateToken(request.headers.authorization);
             if( request.user.role == ROLES.COMPANY_ADMIN ||  request.user.role == ROLES.USER) {
              return true;
            }
           return false;
      }
    
      async validateToken(auth: string) {
        ......
    }
    

    Now to use these guards we just need to use @UseGuards() in our endpoint :

          @Post()
        @UseGuards(AdminGuard)
        async addCompany(@Res() res, @Body() createDto: CompanyDto) {
          ........
        }
    
       @Get(':companyID')
        @UseGuards(EmployeGuard)
        async getcompany(@Res() res, @Param('companyID') companyID) {
           ....
         }
    

    Bonus: you can @useGuards on the controller to make sure the all endpoints use it