NestJs with GraphQl: Roles Guard req.user is undefined

87 Views Asked by At

I am implementing authentication with NestJS and GraphQL using Passport and Guards. When I log in, everything works correctly, but I am only able to access the req.user from Passport in the auth module. When I try to make a request to another endpoint of the API, I have a role guard that checks if the user has the necessary role to continue. However, when I try to do the verification, the req.user is undefined. Does anyone know why?

gql-auth.guard

import {
      ExecutionContext,
      Injectable,
      UnauthorizedException,
    } from '@nestjs/common';
    import { GqlExecutionContext } from '@nestjs/graphql';
    import { AuthGuard } from '@nestjs/passport';

@Injectable()
export class GqlAuthGuard extends AuthGuard('local') {
  constructor() {
    super();
  }
  getRequest(context: ExecutionContext) {
    const ctx = GqlExecutionContext.create(context);
    const request = ctx.getContext();
    request.body = ctx.getArgs();
    return request;
  }

  handleRequest(err: any, user: any) {
    if (err || !user) {
      throw err || new UnauthorizedException();
    }
    return user;
  }
}

local-strategy

import { Injectable, UnauthorizedException } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { Strategy } from 'passport-local';

import { AuthService } from './auth.service';

@Injectable()
export class LocalStrategy extends PassportStrategy(Strategy) {
  constructor(private authService: AuthService) {
    super({
      usernameField: 'email',
    });
  }

  async validate(email: string, password: string): Promise<any> {
    const user = await this.authService.validateUser(email, password);
    if (!user) {
      throw new UnauthorizedException();
    }
    return user;
  }
}

auth resolver

import { UseGuards } from '@nestjs/common';
import { Args, Context, Mutation, Resolver } from '@nestjs/graphql';

import { AuthService } from './auth.service';
import { IsPublic } from './decorators/is-public.decorator';
import { LoginResponse } from './dtos/login-response.dto';
import { GqlAuthGuard } from './gql-auth.guard';

@Resolver()
export class AuthResolver {
  constructor(private authService: AuthService) {}

  @Mutation(() => LoginResponse)
  @IsPublic()
  @UseGuards(GqlAuthGuard)
  async login(
    @Args('email') email: string,
    @Args('password') password: string,
    @Context() context,
  ) {
    const result = await this.authService.login(context.user);
    return result;
  }
}

role-guard

import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { GqlExecutionContext } from '@nestjs/graphql';
import { AuthGuard } from '@nestjs/passport';

import { ROLES_KEY } from './decorators/role.decorator';
import { Role } from './enums/role.enum';
import { JwtAuthGuard } from './jwt-auth.guard';

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

  canActivate(context: ExecutionContext): boolean {
    const ctx = GqlExecutionContext.create(context);
    const { user } = ctx.getContext().req;
    const requiredRoles = this.reflector.getAllAndOverride<Role[]>(ROLES_KEY, [
      context.getHandler(),
      context.getClass(),
    ]);

    if (!requiredRoles) {
      return true;
    }

    return requiredRoles.some((role) => user.role?.includes(role));
  }
}

user.resolver When I try to access this endpoint, the req.user is undefined

@Query(() => [User])
  @IsPublic()
  @Roles(Role.ADMIN, Role.USER)
  async getAll(): Promise<User[]> {
    const result = await this.userService.findAll();
    return result;
  }

é esperado que quando eu acessar qualquer endpoint ele faça a verificação das roles do usuário baseado no req.user

0

There are 0 best solutions below