NestJs Guards Order

592 Views Asked by At

I have problems with NestJs Guards, despite the correct order which I got from here: https://docs.nestjs.com/faq/request-lifecycle there still seems to be problems.

I am aware that the AuthGuard binds the user to the request via the password strategy, however I am not quite sure why I don't have this in the 2nd guard anymore. While debugging I noticed that the AbilityGuard is also executed before the AuthGuard, which can't be according to the documentation. Can someone help me here? I have found the following pages:

Can't retrieve the request.user from my RoleGuard, nestJS

@ApiTags('Tenant')
@Controller('tenant')
@UseGuards(new JwtAuthenticationGuard())
export class TenantController {
  private readonly _logger = new Logger(TenantController.name);

  constructor(
    @Inject(TenantService) private readonly _tenantService: TenantService
    ) {}


  @Post()
  @CheckAbilities({action: UserAction.CREATE, subject: User})
  @UseGuards(AbilitiesGuard)
  async create(@CurrentUser() user: User, @Body() createTenantDto: CreateTenantDto) {
    try {
      return await this._tenantService.create(user,createTenantDto);
    } catch (error) { 
      throw error;
    }
  }
import { AuthGuard } from '@nestjs/passport';

export class JwtAuthenticationGuard extends AuthGuard('jwt') {
  constructor() {
    super();
  }
}
import { CHECK_ABILITY, RequiredRule } from "./ability.decorator";
import { CanActivate, ExecutionContext, ForbiddenException, Injectable } from "@nestjs/common";

import { AbilityFactory } from "./ability-factory.service";
import { ForbiddenError } from "@casl/ability";
import { Reflector } from "@nestjs/core/services";

@Injectable()
export class AbilitiesGuard implements CanActivate {
    
    constructor(
        private reflector: Reflector,
        private abilityFactory: AbilityFactory,
    ) {}

    async canActivate(context: ExecutionContext): Promise<boolean> {
        const rules = this.reflector.get<RequiredRule[]>(CHECK_ABILITY, context.getHandler()) || [];

        if (!rules) {
            return true;
        }

        const request = context.switchToHttp().getRequest();
        
        const { user } = request.user;
        console.log(user)
        const ability = this.abilityFactory.defineAbility(user);

        try {
            rules.forEach((rule) => ForbiddenError.from(ability).throwUnlessCan(rule.action, rule.subject))
            return true
        }
        catch (error) {
            if (error instanceof ForbiddenError) {
                throw new ForbiddenException(error.message);
            }
        }
    }
}

Can't retrieve the request.user from my RoleGuard, nestJS

1

There are 1 best solutions below

0
On

user is most likely not a property on req.user. You should just assign to a variable instead of deconstructing

const user = request.user;

, or deconstruct from the parent object.

const { user } = request;