admin管理员组

文章数量:1403069

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?

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?

Share Improve this question edited Apr 2, 2019 at 14:32 Kim Kern 60.7k20 gold badges218 silver badges214 bronze badges asked Apr 2, 2019 at 13:58 Fabio PicheliFabio Picheli 95911 silver badges29 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 8

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.

This is what worked for me

jwt.guard.ts

import { AuthGuard } from '@nestjs/passport';

export class JwtGuard extends AuthGuard('jwt') {
  constructor() {
    super();
  }
}

app.module.ts

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
    }),
  ],
  providers: [
    {
      provide: APP_GUARD,
      useClass: JwtGuard,
    },
    {
      provide: APP_GUARD,
      useClass: RoleGuard,
    },
  ],
})
export class AppModule {}

role.decorator.ts

import { SetMetadata } from '@nestjs/mon';
import { Role } from 'mon/enums';

export const ROLE_KEY = 'role';
export const AllowRole = (role: Role) => SetMetadata(ROLE_KEY, role);

role.guard.ts

import { CanActivate, ExecutionContext, Injectable } from '@nestjs/mon';
import { Reflector } from '@nestjs/core';
import { ROLE_KEY } from 'mon/decorators';
import { Role } from 'mon/enums';

@Injectable()
export class RoleGuard implements CanActivate {
  constructor(private reflector: Reflector) {}

  canActivate(context: ExecutionContext): boolean {
    const requiredRole = this.reflector.getAllAndOverride<Role>(ROLE_KEY, [
      context.getHandler(),
      context.getClass(),
    ]);

    if (!requiredRole) {
      return true;
    }

    const { user } = context.switchToHttp().getRequest();
    console.log({ requiredRole });
    console.log({ user });
    return user.role === requiredRole;
  }
}

本文标签: javascriptNestJSHow to use RoleGuard with JWTStack Overflow