Dario Rinaldi
Dario Rinaldi

Reputation: 23

Unable to set cookie in NestJS GraphQL

we have a NestJS GraphQL server running and we are trying to set an httpOnly cookie in an interceptor. The set seems to work if we call the mutation by Postman, showing the cookie in the cookies tab. But calling the mutation from the Playground, there is no trace of the cookie in the browser. Even accessing the request.cookies property in a guard gives us no results. What are we doing wrong?

The server is fastify based and we are using fastify-cookie library to set the cookie.

The interceptor code is:

@Injectable()
export class AccessTokenCookieInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler<AccessTokens>): Observable<any> {
    const ctx = GqlExecutionContext.create(context);
    const response: FastifyReply = ctx.getContext().response;
    return next.handle().pipe(
      tap(data => {
        response.setCookie('my_cookie', JSON.stringify(data), {
          httpOnly: true,
          path: '/',
        });
      }),
    );
  }
}

The GQLModule:

GraphQLModule.forRoot({
  autoSchemaFile: join(process.cwd(), 'src/schema.gql'),
  sortSchema: true,
  context: ({ request, reply }) => {
    return {
      request,
      response: reply,
    };
  },
  ...
}),

The guard where we read the cookie:

@Injectable()
export class AccessTokenGuard implements CanActivate {
  async canActivate(context: ExecutionContext): Promise<boolean> {
    const ctx = GqlExecutionContext.create(context);
    const request = ctx.getContext().request;

    const cookie = request.cookies['my_cookie'];
    const tokens: AccessTokens = JSON.parse(cookie);

    request.finxTokens = tokens;

    return true;
  }
}

Thank you for your help!

Upvotes: 2

Views: 4702

Answers (2)

kartikhedau
kartikhedau

Reputation: 21

This worked for me. Add below code in class GqlAuthGuard extends AuthGuard('local')

handleRequest(err, user, info, context) {
    if (err || !user || info) throw err || new UnauthorizedException();

    const accessToken = this.jwtService.sign({ ... });
    const gqlExecutionContext = GqlExecutionContext.create(context);
    const request = gqlExecutionContext.getContext().req;
    request.res?.cookie('access_token', accessToken);
    return user;
  }

Upvotes: 0

ismailkurar
ismailkurar

Reputation: 191

1 - You need to add cors settings to your GQLModule;

GraphQLModule.forRoot({
  ...
   cors: {
     credentials: true,
     origin: true
   }
})

2 - In your apollo client settings to tell your network interface to send the cookie along with every request. You just need to pass the credentials option;

 const httpLink = new HttpLink({ uri: 'graphql', credentials: 'include' });

Upvotes: 4

Related Questions