javascript - NestJS - Ako použiť RoleGuard s JWT?
V súčasnosti sa mi podarilo použiť AuthGuard s JWT autentifikáciou, ale nepodarilo sa mi získať user v Roles.
Snažil som sa nasledovať príklad mačiek, ale nikdy sa mi nepodarí definovať objekt user, ako vidíte na riadku 14.
Toto je môj kód:
// 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 {}
Všetko ostatné je presne ako v príklade v repozitári. Máte nejaký nápad, ako sa dajú získať definovaní users?
Odpoveď č. 1
AuthGuard() musí bežať pred RolesGuard, aby ste boli autentifikovaní a vlastnosť user bola nastavená.
Pokiaľ viem, neexistuje iný spôsob, ako zmeniť poradie vašich strážcov, než ich definovaním ako:
@UseGuards(AuthGuard(), RolesGuard)
V tejto záležitosti prebieha diskusia o potenciálnom API na zmenu hierarchie vykonávania strážcov.
Tento problém spomína alternatívne riešenie:
Pre tento prípad použitia mám pocit, že by bolo lepšie umiestniť autentifikačnú logiku do middleware, pretože sa spustí pred ochrancom.
Odpoveď č. 2
Toto fungovalo mne
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 {}
rola.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);
role.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;
}
}
