'How can I set a session key from inside a GraphQL resolver in NestJS?

I'm discovering Nest.js and I want to setup a cookie based authentication system with GraphQL.

I already installed express-session middleware, here is the configuration:

main.ts

 app.use(
    session({
      store: new redisStore({
        client: redis
      } as any),
      name: 'qid',
      secret: SESSION_SECRET,
      resave: false,
      saveUninitialized: false,
      cookie: {
        httpOnly: true,
        secure: !isDev,
        maxAge: 1000 * 60 * 60 * 24 * 7 * 365
      }
    })
  )

it works fine because when I do :

 app.use((req: any, res: any, next: any) => {
      // Debug purpose
      req.session.userId = '42'
      next()
    })

The cookie is added.

Right now I have two mutations, register and login. In the login mutation (or in the userService), after I found a user I want to do something like req.session.userId = user.id but I can't find a way to do this.

I tried to add @Context() ctx to my mutation. If I console log ctx, it contains everything I expect (req.session.id for example)

But if I do ctx.req.session.userId = 'something', the cookie is not set!

Here is my mutation:

user.resolver.ts

@Mutation('login')
  async login(
    @Args('email') email: string,
    @Args('password') password: string,
    @Context() ctx: any
  ) {
    console.log(ctx.req.session.id) // Show the actual session id
    ctx.req.session.userId = 'something' // Do not set any cookie
    return await this.userService.login(email, password)
  }
}

I am totally lost and I really need help, I'd love to understand what's happening. I know I'm probably doing this totally wrong but I'm new to both Nest and GraphQL..

Thank you guys...



Solution 1:[1]

I found the problem after many days ... and it was...

GraphQL Playground -> Settings -> add "request.credentials": "include" (and no "omit")

Hope it will help someone..

Solution 2:[2]

for this, it's better to do the configuration in the GraphQL config file instead of the client side

graphql.config.ts

import { ApolloDriverConfig, ApolloDriver } from '@nestjs/apollo';
import { join } from 'path';

export const GraphQLConfig: ApolloDriverConfig = {
  driver: ApolloDriver,
  debug: true,
  autoSchemaFile: join(process.cwd(), 'src/schema.gql'),
  playground: {
    settings: {
      'editor.theme': 'light', // use value dark if you want a dark theme in the playground
      'request.credentials': 'include',
    },
  },
};

and assign the config file to the module directory

user.module.ts

import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import { TypeOrmModule } from '@nestjs/typeorm';
import { GraphQLConfig } from 'src/config/graphql.config';
import { UserEntity } from 'src/entity/user.entity';
import { UserResolver } from './user.resolver';
import { UserService } from './user.service';

@Module({
  imports: [
    TypeOrmModule.forFeature([UserEntity]),
    GraphQLModule.forRoot(GraphQLConfig),
  ],
  providers: [UserService, UserResolver],
})
export class UserModule {}

and it will automatically enable credentials value to be "include" from "omit"

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Mika Void
Solution 2 Raj Gohil