javascript - NestJS - Cum să folosești RoleGuard cu JWT?
În prezent, am reușit să folosesc AuthGuard cu autentificare JWT, dar nu reușesc să obțin user pe Roles.
Am încercat să urmez exemplul pisicilor, dar nu reușesc niciodată să definesc obiectul user, poți vedea pe linia 14.
Acesta este codul meu:
// 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 {}
Tot restul este exact ca exemplul din depozit. Ai vreo idee cum să poți obține users definite?
Răspuns #1
AuthGuard() trebuie să ruleze înainte de RolesGuard astfel încât să fiți autentificat și proprietatea user să fie setată.
Din câte știu, nu există altă modalitate de a schimba ordinea gărzii tale decât să le definești astfel:
@UseGuards(AuthGuard(), RolesGuard)
Există o discuție despre un API potențial pentru schimbarea ierarhiei de execuție a gardienilor în această problemă.
Această problemă menționează o soluție alternativă:
pentru acest caz de utilizare, simt că ar fi mai bine să pun logica de autentificare într-un middleware, deoarece rulează înainte de gard.
Răspunsul #2
Asta a funcționat pentru mine
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 {}
rol.decorator.ts
import { SetMetadata } from '@nestjs/common';
import { Role } from 'common/enums';
export const ROLE_KEY = 'role';
export const AllowRole = (role: Role) => SetMetadata(ROLE_KEY, role);
rol.guard.ts
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { ROLE_KEY } from 'common/decorators';
import { Role } from 'common/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;
}
}
