nestjsnestjs-passportnestjs-jwt

Nestjs JwtStrategy access to context


I have a UseGuard in my WebSocket. Actually, this guard is a JwtAuthGuard that extends AuthGuard('jwt'). The JwtAuthGuard has a Strategy class called JwtStrategy. In this class, I have a validate method. In HTTP-based requests I return payload in this method. Then nestjs attach the payload to the req. Here is my Strategy class:

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor(private authConfigService: AuthConfigService) {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      ignoreExpiration: false,
      secretOrKey: authConfigService.JWT_SECRET,
    });
  }

  async validate(payload: any) {
    return payload;
  }
}

I want to have access to context within validate method in order to attach the payload to the WebSocket's body (or anything that I can have access to the payload). Any idea?


Solution

  • You don't need to make any modifications to your strategy class. Instead, you should modify your JwtAuthGuard's getRequest method (if you don't have one then you should make one) that returns an object that has a headers proeprty that is an object with a authorization property that is a string. Something like

    @Injectable()
    export class JwtAuthGuard extends AuthGuard('jwt') {
      getRequest(context: ExecutionContext) {
        const ws = context.switchToWs().getClient(); // possibly `getData()` instead.
        return {
          headers: {
            authorization: valueFromWs(ws),
          }
        }
      }
    }
    

    You can also make this work across different context types by using an if/else or a switch statement and returning the correct object based on the contextType from context.getType(). Whatever is returned from this getRequest method is where passport will end up attaching the user property, so it may make sense to return the entire client with these extra values.