未使用 Nestjs 设置 HTTP Cookie

HTTP Cookie not being set with Nestjs

我有一个名为 login 的 GQL 突变,它 returns JWT 作为响应中的 cookie。

虽然 Set-Cookie header 存在,但我的本地存储选项卡中没有显示任何内容。我的控制台也没有打印任何内容...

这是我的登录突变

@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
}

响应示例 JSON:

{
  "data": {
    "login": {
      "jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjI0N2QyNmY3LTM3NzQtNGRiNS1hM2MzLTE2MTg3Mzk2ODdlMCIsImVtYWlsIjoidmluZWhlcmJpZUBnbWFpbC5jb20iLCJpYXQiOjE2MzYxMjkyMTksImV4cCI6MTYzODcyMTIxOX0.hHHAAgzs7wFjMP2C565fGGHAd0o-C9h-jA5qzm48OdE",
      "user": {
        "email": "email@gmail.com",
        "name": "Some Name"
      }
    }
  }
}

回复:

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

要求:

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

目前,我还没有设置我的 front-end 代码库,它将设置为 http://localhost:4000。这一切都在 GraphQL 操场上进行测试

更新

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
}

应用程序模块:

@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 {}

授权模块:

@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 {}

默认情况下,GQL playground 不发送凭据。在 GQL playground 的选项中,设置 request.credentials = 'include' 它应该有效