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