javascript - NestJS - Kuinka käyttää RoleGuardia JWT:n kanssa?


Tällä hetkellä olen onnistunut käyttämään AuthGuardia JWT-todennuksella, mutta en onnistu saamaan käyttäjää Roolit-kohdassa.

Olen yrittänyt seurata kissan esimerkkiä, mutta en koskaan saa user-oliota määriteltyä, kuten näet rivillä 14.

Tässä on koodini:

// 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 {}

Kaikki muu on tarkalleen kuten esimerkissä säilytyspaikassa. Onko mitään ideaa, miten voisi saada määriteltyä users?

Vastaus #1

AuthGuard() täytyy suorittaa ennen RolesGuard-ohjainta, jotta olet todennettu ja user-ominaisuus on asetettu.

Tietääkseni ei ole muuta tapaa muuttaa vartijoidensi järjestystä kuin määrittelemällä ne seuraavasti:

@UseGuards(AuthGuard(), RolesGuard)

Tässä asiassa käydään keskustelua mahdollisesta API:sta vartijoiden suoritushierarkian muuttamiseksi.

Tässä asiassa mainitaan vaihtoehtoinen ratkaisu:

Tässä käyttötapauksessa tuntuu siltä, että todennuslogiikan laittaminen middlewareen olisi parempi, koska se suoritetaan ennen vartijaa.

Vastaus #2

Tämä toimi minulle

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 {}

rooli.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);

rooli.vartija.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;
  }
}