Home > Software design >  HTTP Cookie not being set with Nestjs
HTTP Cookie not being set with Nestjs

Time:11-06

I have a GQL mutation called login, which returns a JWT as a cookie in the response.

Although the Set-Cookie header is present, nothing appears in my local storage tab. Nothing gets printed in my console either...

Here's my login mutation

@Mutation((returns) => AuthenticatedUser)
async login(
  @Context() context: Auth.GqlContext,
  @Args('payload', { type: () => UserLoginDto }) payload: UserLoginDto
): Promise<AuthenticatedUser> {
  const authenticatedUser = await this.authService.login(payload)

  context.res.cookie('jwt', authenticatedUser.jwt, {
    httpOnly: true,
    secure: process.env.NODE_ENV === 'production',
    sameSite: 'lax',
    maxAge: 1000 * 60 * 60 * 24 * 31, // one month
    domain: process.env.NODE_ENV === 'production' ? '.herbievine.com' : undefined 
  })

  return authenticatedUser
}

Example response as JSON:

{
  "data": {
    "login": {
      "jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjI0N2QyNmY3LTM3NzQtNGRiNS1hM2MzLTE2MTg3Mzk2ODdlMCIsImVtYWlsIjoidmluZWhlcmJpZUBnbWFpbC5jb20iLCJpYXQiOjE2MzYxMjkyMTksImV4cCI6MTYzODcyMTIxOX0.hHHAAgzs7wFjMP2C565fGGHAd0o-C9h-jA5qzm48OdE",
      "user": {
        "email": "[email protected]",
        "name": "Some Name"
      }
    }
  }
}

Response:

HTTP/1.1 200 OK
X-Powered-By: Express
Access-Control-Allow-Origin: http://localhost:4000
Vary: Origin
Access-Control-Allow-Credentials: true
Set-Cookie: jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjI0N2QyNmY3LTM3NzQtNGRiNS1hM2MzLTE2MTg3Mzk2ODdlMCIsImVtYWlsIjoidmluZWhlcmJpZUBnbWFpbC5jb20iLCJpYXQiOjE2MzYxMjkyMTksImV4cCI6MTYzODcyMTIxOX0.hHHAAgzs7wFjMP2C565fGGHAd0o-C9h-jA5qzm48OdE; Max-Age=2678400; Path=/; Expires=Mon, 06 Dec 2021 16:06:11 GMT; HttpOnly; SameSite=Lax
Content-Type: application/json; charset=utf-8
Content-Length: 319
ETag: W/"13f-MuV4uipvL8ui1YJXuTSvJ1TM1H0"
Date: Fri, 05 Nov 2021 16:06:11 GMT
Connection: keep-alive
Keep-Alive: timeout=5

Request:

POST /graphql HTTP/1.1
Host: localhost:3000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:78.0) Gecko/20100101 Firefox/78.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://localhost:3000/graphql
content-type: application/json
Origin: http://localhost:3000
Content-Length: 195
Connection: keep-alive

For the moment, I still haven't setup my front-end codebase, which will be set to http://localhost:4000. This is all being tested in the GraphQL playground

Update

config for gql playground:

{
  "editor.cursorShape": "line",
  "editor.fontFamily": "'Source Code Pro', 'Consolas', 'Inconsolata', 'Droid Sans Mono', 'Monaco', monospace",
  "editor.fontSize": 14,
  "editor.reuseHeaders": true,
  "editor.theme": "dark",
  "general.betaUpdates": false,
  "prettier.printWidth": 80,
  "prettier.tabWidth": 2,
  "prettier.useTabs": false,
  "request.credentials": "omit",
  "schema.disableComments": true,
  "schema.polling.enable": true,
  "schema.polling.endpointFilter": "*localhost*",
  "schema.polling.interval": 2000,
  "tracing.hideTracingResponse": true,
  "queryPlan.hideQueryPlanResponse": true
}

App Module:

@Module({
  imports: [
    GraphQLModule.forRoot({
      autoSchemaFile: join(process.cwd(), 'schema.gql'),
      context: ({ req, res }) => ({ req, res }),
      cors: {
        origin:
          process.env.NODE_ENV === 'production'
            ? '.herbievine.com'
            : 'http://localhost:4000',
        credentials: true,
      }
    }),
    ThrottlerModule.forRoot({
      ttl: 60,
      limit: 20
    }),
    PostsModule,
    CategoriesModule,
    UsersModule,
    AuthModule
  ],
  controllers: [AppController],
  providers: [AppService, PrismaService]
})
export class AppModule {}

Auth Module:

@Module({
  imports: [
    PassportModule.register({ defaultStrategy: 'jwt' }),
    JwtModule.register({
      secret: process.env.JWT_SECRET,
      signOptions: {
        expiresIn: '30d'
      }
    })
  ],
  providers: [
    PrismaService,
    JwtStrategy,
    LocalStrategy,
    AuthService,
    UsersService,
    AuthResolver
  ],
  controllers: [AuthController],
  exports: [AuthService]
})
export class AuthModule {}

CodePudding user response:

The GQL playground by default doesn't send credentials. In the options of the GQL playground, set request.credentials = 'include' and it should work

  • Related