Search code examples
node.jstypescriptjwtnestjspassport-jwt

I'm using a passport-jwt auth strategy in my nestJS app (with authGuard), how to get access to the token payload in my controller?


I'm trying to get access to the jwt payload in a route that is protected by an AuthGuard.

I'm using passport-jwt and the token payload is the email of the user.

I could achieve this by runing the code bellow:

import {
    Controller,
    Headers,
    Post,
    UseGuards,
} from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { AuthGuard } from '@nestjs/passport';

@Post()
@UseGuards(AuthGuard())
async create(@Headers() headers: any) {
    Logger.log(this.jwtService.decode(headers.authorization.split(' ')[1]));
}

I want to know if there's a better way to do it?


Solution

  • Your JwtStrategy has a validate method. Here you have access to the JwtPayload. The return value of this method will be attached to the request (by default under the property user). So you can return whatever you need from the payload here:

    async validate(payload: JwtPayload) {
      // You can fetch additional information if needed 
      const user = await this.userService.findUser(payload);
      if (!user) {
        throw new UnauthorizedException();
      }
      return {user, email: payload.email};
    }
    

    And then access it in you controller by injecting the request:

    @Post()
    @UseGuards(AuthGuard())
    async create(@Req() request) {
        Logger.log(req.user.email);
    }
    

    You can make this more convenient by creating a custom decorator:

    import { createParamDecorator } from '@nestjs/common';
    
    export const User = createParamDecorator((data, req) => {
      return req.user;
    });
    

    and then inject @User instead of @Req.