FlushBG
FlushBG

Reputation: 281

NestJS - Passport JWT strategy does not attach user to request object

I am building an auth flow using NextAuth on a Next.js frontend, and Passport JWT on a NestJS + GraphQL backend. NextAuth gets a JWT token from a third party provider, and then attaches it to the auth header. In the backend, it is handled by a global auth guard.

Here is the guard:

@Injectable()
export class GqlAuthGuard extends AuthGuard('jwt') {
  constructor(@Inject(UserRoleMetadataService) private readonly userRoleMetadataService: UserRoleMetadataService) {
    super();
  }

  canActivate(context: ExecutionContext): boolean | Promise<boolean> | Observable<boolean> {
    if (this.userRoleMetadataService.isPublicResource(context)) {
      return true;
    }

    return super.canActivate(context);
  }

  getRequest(context: ExecutionContext) {
    const ctx = GqlExecutionContext.create(context);
    return this.userRoleMetadataService.getRequestWithAuthHeaders(ctx);
  }
}

Validate method from strategy:

async validate(req, payload: KnomeJwtPayload): Promise<UserEntity> {
    const user = await this.userService.getOrCreateUser(payload);

    await this.verifyAuthorization(req, user.roles);
    const isOwnerRequired = this.userRoleMetadataService.readIsOwnerRequiredHeader(req);
    if (isOwnerRequired) {
      this.verifyOwnership(req, user.id);
    }

    return user;
  }

and user decorator:

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

Everything is working as expected up until the return statement from the strategy. I logged the user object that is returned, and it is exactly what I expect. However, for some reason that user object is not being attached to the request and is therefore undefined in the decorator. What am I doing wrong?

Upvotes: 0

Views: 972

Answers (1)

Jay McDoniel
Jay McDoniel

Reputation: 70510

The object returned by the getRequest method needs to be the same instance as ctx.req so that when you access ctx.req it has the new properties. As you mentioned in a comment it was a shallow copy but has been reworked to be the same object reference

Upvotes: 1

Related Questions