1

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?

Vahid Najafi
  • 4,654
  • 11
  • 43
  • 88
  • What do you mean by `context`? What is it you're trying to do? – Jay McDoniel Jul 12 '21 at 19:41
  • @JayMcDoniel the same thing that we can do in the guards `canActivate` method that you can have access to the Execution context. For your second question, I want to attach the payload to something related to WS, then I can access to the payload in my web socket service. (The same thing that nestjs does for HTTP. In this case it sets the payload to the `req`) – Vahid Najafi Jul 12 '21 at 19:45

1 Answers1

2

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.

Jay McDoniel
  • 57,339
  • 7
  • 135
  • 147
  • Thank you. As I knew, we determine about attaching the payload in the Strategy class's `validate` method that we return payload. But I can test it. And one more question, how can I access this user property in WS service? – Vahid Najafi Jul 12 '21 at 20:02
  • The thing that I've done is to do the similar thing in `canActivate` method. I get the token from WS and attach it to HTTP's header. So nestjs behave the request like an HTTP request. But didn't know how to do it in Strategy (in validate method) – Vahid Najafi Jul 12 '21 at 20:06
  • As I mentioned, whatever you return from `getRequest` is the object that Passport attaches the user to. If you want that to be on the WS Client, then you need to get an object off of the `client` and return it with the properties mentioned. Then passport will attach the user back to this object. You really shouldn't be worrying about doing anything in the strategy other than validating the request – Jay McDoniel Jul 12 '21 at 20:22
  • Thank you. Is it exist in the nestjs documentation? Because I didn't see it anywhere – Vahid Najafi Jul 13 '21 at 10:47
  • Under the [GraphQL](https://docs.nestjs.com/controllers#request-object) section – Jay McDoniel Jul 13 '21 at 15:02