Search code examples
javascriptnode.jstypescriptnestjs

NestJS - How to use RoleGuard with JWT?


Currently, I've managed to use AuthGuard with JWT authentication, but I'm not managing to get the user on Roles.

I've tried to follow the cats example, but I never get the user object defined, you can see on line 14.

This is my code:

// auth.controller.ts
@Controller('auth')
@UseGuards(RolesGuard)
export class AuthController {
  constructor(private readonly authService: AuthService) {}

  @Get('token')
  async createToken(): Promise<any> {
    return await this.authService.createToken();
  }

  @Post()
  @UseGuards(AuthGuard())
  @Roles('admin')
  findAll() {
    // this route is restricted by AuthGuard
    // JWT strategy
    return 'Super important info';
  }
}


// auth.module.ts
@Module({
  imports: [
    SharedModule,
    PassportModule.register({ defaultStrategy: 'jwt' }),
    JwtModule.registerAsync({
      imports: [SharedModule],
      useFactory: async (configService: ConfigService) => ({
        secretOrPrivateKey: configService.get('SECRET_KEY'),
        signOptions: {
          expiresIn: configService.get('SECRET_KEY_EXPIRES'),
        },
      }),
      inject: [ConfigService],
    }),
  ],
  controllers: [AuthController],
  providers: [
    AuthService,
    JwtStrategy,
  ],
})
export class AuthModule {}

All the rest is exactly as the example on the repository. Any idea how to be able to get the users defined?


Solution

  • The AuthGuard() has to run before the RolesGuard so that you are authenticated and the user property is set.

    As far as I know there is no other way to change the order of your guards other then defining them as:

    @UseGuards(AuthGuard(), RolesGuard)
    

    There is a discussion about a potential API for changing the exeuction hierarchy of guards in this issue.


    This issue mentions an alternative solution:

    for this use case, i feel like putting authentication logic in a middleware would be better, as it runs before the guard.