NestJS Get current user in GraphQL resolver authenticated with JWT

Wish I could take any sort of credit here, I'm simply passing along information from the course, NestJS Zero To Hero (absolutely fantastic btw).

For NestJS 7:

// get-user.decorator.ts

import { createParamDecorator, ExecutionContext } from '@nestjs/common';

import { User } from '../../user/entity/user.entity';

export const GetAuthenticatedUser = createParamDecorator((data, ctx: ExecutionContext): User => {
  const req = ctx.switchToHttp().getRequest();
  return req.user;
});

You can implement this however you like. I have an auth.controller that looks something like this:

// auth.controller.ts

import { GetAuthenticatedUser } from './decarator/get-user.decorator';

...

@Controller('api/v1/auth')
export class AuthController {
  constructor(private authService: AuthService) {
    //
  }

  ...

  /**
   * Get the currently authenticated user.
   *
   * @param user
   */
   @Post('/user')
   @UseGuards(AuthGuard())
   async getAuthenticatedUser(@GetAuthenticatedUser() user: User) {
     console.log('user', user);
   }

Result is something like this:

// console.log output:

user User {
  id: 1,
  email: '[email protected]',
  ...
}

In order to use an AuthGuard with GraphQL, extend the built-in AuthGuard class and override the getRequest() method. Create a file called gql.guard.ts (Naming your wish)

@Injectable()
export class GqlAuthGuard extends AuthGuard('jwt') {
  getRequest(context: ExecutionContext) {
    const ctx = GqlExecutionContext.create(context);
    return ctx.getContext().req;
  }
}

To get the current authenticated user in your graphql resolver, you can define a @CurrentUser() decorator (create a file called user.decorator.graphql.ts)

import { createParamDecorator, ExecutionContext } from '@nestjs/common';
import { GqlExecutionContext } from '@nestjs/graphql';

export const CurrentUser = createParamDecorator(
  (data: unknown, context: ExecutionContext) => {
    const ctx = GqlExecutionContext.create(context);
    return ctx.getContext().req.user;
  },
);

To use above decorator in your resolver, be sure to include it as a parameter of your query or mutation

@Query(returns => User)
@UseGuards(GqlAuthGuard)
whoAmI(@CurrentUser() user: User) {
  return this.usersService.findById(user.id);
}

Read More : https://docs.nestjs.com/security/authentication#graphql


Finally found the answer ... https://github.com/nestjs/graphql/issues/48#issuecomment-420693225 pointed me into the right direction of creating a user decorator

// user.decorator.ts
import { createParamDecorator } from '@nestjs/common';

export const CurrentUser = createParamDecorator(
  (data, req) => req.user,
);

And then use this in my resolver method:

 import { User as CurrentUser } from './user.decorator';

 @Query(returns => User)
  @UseGuards(GqlAuthGuard)
  whoami(@CurrentUser() user: User) {
    console.log(user);
    return this.userService.findByUsername(user.username);
  }

Now everything works as expected. So all credits of this answer goes to https://github.com/cschroeter


Another approach is to validate web token with whatever package you are using, then create decorator get-user.decorator.ts

import { createParamDecorator, ExecutionContext } from '@nestjs/common';
import { GqlExecutionContext } from '@nestjs/graphql';


export const GetUser = createParamDecorator((data, context: ExecutionContext)  => {
 const ctx = GqlExecutionContext.create(context).getContext();
return ctx.user
});

then in your resolver, you can use this decorator (@GetUser() user: User) to access the user