typescript - Hur man ställer in en HTTP-only cookie i NestJS


Jag försöker implementera JWT-auktorisering med accessToken och refreshToken. Både accessToken och refreshToken behöver sättas i en HTTP-only cookie.

Jag försökte denna kod men den sätter inte cookies. Jag använder NestJS-ramverket här.

import { Controller, Request, Post, Body, Response } from '@nestjs/common';
@Controller()
export class UserController {
  constructor() {}

  @Post('users/login')
  async login(
    @Request() req,
    @Body() credentials: { username: string; password: string },
    @Response() res,
  ) {
    try {
      // Login with username and password
      const accessToken = 'something';
      const refreshToken = 'something';
      const user = { username: credentials.username };

      res.cookie('accessToken', accessToken, {
        expires: new Date(new Date().getTime() + 30 * 1000),
        sameSite: 'strict',
        httpOnly: true,
      });
      return res.send(user);
    } catch (error) {
      throw error;
    }
  }
}

Metoden res.send() fungerar bra, jag får data i svaret. Hur kan jag sätta en cookie här?

Detta är min main.ts-fil: -

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { Logger } from '@nestjs/common';
import { AuthenticatedSocketIoAdapter } from './chat/authchat.adapter';
import * as cookieParser from 'cookie-parser';
async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.enableCors();
  app.use(cookieParser());
  app.useWebSocketAdapter(new AuthenticatedSocketIoAdapter(app));
  await app.listen(3000);
  Logger.log('User microservice running');
}
bootstrap();

Och för att få kakan använder jag:-

request.cookies

Svar #1

Konversation i kommentarerna:

Axios, på klientsidan, behöver ha withCredentials inställt på true för att skicka tillbaka kakorna till servern. Servern skickade och satte kakorna som förväntat.

Svar #2

Jag stötte på nästan samma problem som du. Axios kunde inte spara kakorna. Chrome krävde att man satte upp SameSite: 'none', secure: true. Ändå fungerade det inte. Det sparade kakan med fetch-metoden, men bara i webbläsare som körs med Chromium... Så Mozilla fick den inte. Min axios var:

const response = await axios.post(url+'/login', loginState, {withCredentials: true});

Backend Nestjs: Main.ts:

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.setGlobalPrefix('v1/api');
  app.use(cookieParser());
  app.useGlobalPipes(new ValidationPipe());
  app.enableCors({
    credentials: true,
    origin: process.env.FRONTEND_URL,
  })
  await app.listen(3000);
}

Min AuthService-inloggningsfunktion (kom ihåg om passthrought: true i Res)

@Post('login')
async login(
        @Body()body: LoginUserDTO,
        @Res({passthrough: true}) response: Response
    ): Promise<any> {
    const user = await this.userService.getOne({where: {"user_email": body.email}});
    if(!user) {
        throw new NotFoundException('User not found')
    }
    if(!await bcrypt.compare(body.password, user.user_password)) {
        throw new BadRequestException('Password incorrect');
    }
    const frontendDomain = this.configService.get<string>('FRONTEND_DOMAIN');
    const jwtToken = await this.jwtService.signAsync({id: user.user_id});
    response.cookie('jwt', jwtToken, {httpOnly: true, domain: frontendDomain,});

    return {'jwt': jwtToken}
}

Konstigt nog var det som löste mitt problem att lägga till domänen i response.cookie.

Även mina utvecklingsmiljövariabler som används för CORS och cookie-domän:

FRONTEND_URL = http://localhost:3333
FRONTEND_DOMAIN = localhost

Hoppas att min kod kan hjälpa

Relaterade artiklar