본문 바로가기

항해99_10기/105일의 TIL & WIL

[4주차] [20221206] thunder client에서 req.cookies 넘기기

오늘은 게시판 CRUD 과제에서, 회원 로그인 및 인증 api를 access/refresh token을 이용하여 인증 middleware를 업그레이드 했다.

 

api를 모두 짜고, thunder client에서 테스트를 하고 싶었는데, 도무지 req.cookies 값을 넣어주는 방법을 찾지를 못했다.

  1. 사용자가 로그인을 하면 서버에서는 accessToken과 refreshToken을 발급해서 res.cookie로 클라에 넘겨준다.
  2. 쿠키로 토큰 값을 전달 받은 클라는 사용자가 인증이 필요한 서비스를 사용할때마다 저장해서 가지고 있던 토큰이 담기 쿠키를 req.cookies로 서버에 날린다.
  3. 서버에서는 cookie-parser 미들웨어를 사용해서 req.cookies에 담긴 토큰 값을 가져온다.
    • 프론트 없이 서버만 만들고 있는 나의 입장에서, thunder client를 통해 req 값을 날려줘야 하는데, 이게 은근히 자료도 잘 안나오고 어려웠다.
// 로그인 api

router.post("/login", async (req, res) => {
  try {
    const { nickname, password } = await postAuthSchema.validateAsync(req.body);
    const user = await Users.findOne({ where: { nickname } });

    if (!user || password !== user.password) {
      res
        .status(412)
        .send({ errorMessage: "닉네임 또는 패스워드를 확인해주세요." });
      return;
    }

    const accessToken = createAccessToken(user.userId);
    const refreshToken = createRefreshToken();
    console.log("typeof token", typeof accessToken);

    tokenObject[refreshToken] = user.userId;
    res.cookie("accessToken", accessToken);		// 토큰을 발행해 res.cookie로 날린다.
    res.cookie("refreshToken", refreshToken);	// 토큰을 발행해 res.cookie로 날린다.

    return res
      .status(200)
      .send({ message: "Token이 정상적으로 발급되었습니다." });
  } catch (err) {
    console.log(err);
    if (err.name === "CustomError") {
      return res.status(err.status).send({ errorMessage: err.message });
    } else
      return res
        .status(400)
        .send({ errorMessage: "요청한 데이터 형식이 올바르지 않습니다." });
  }
});



// 인증 미들웨어에서 클라에서 날린 req.cookie를 파싱해서 토큰을 인증한다.
async (req, res, next) => {
  try {
    const { accessToken, refreshToken } = req.cookies;	// 요 값을 전달하기 위해 썬드 클라이언트의 여러가지 방법을 찾아보았다.

    if (!accessToken || !refreshToken) {
      res.status(401).send({ errorMessage: "로그인 후 이용 가능합니다." });
      return;
    }

    const isAccessTokenValid = validateAccessToken(accessToken);
    const isRefreshTokenValid = validateRefreshToken(refreshToken);

    if (!isRefreshTokenValid)
      return res
        .status(419)
        .json({ message: "Refresh Token이 만료되었습니다." });

    if (!isAccessTokenValid) {
      const accessTokenId = tokenObject[refreshToken];
      console.log("tokenObject", tokenObject);
      if (!accessTokenId)
        return res.status(419).json({
          message: "Refresh Token의 정보가 서버에 존재하지 않습니다.",
        });

      const newAccessToken = createAccessToken(accessTokenId);
      res.cookie("accessToken", newAccessToken);
      return res.json({ message: "AccessToken을 새롭게 발급하였습니다." });
    }

    try {
      const { userId } = getAccessTokenPayload(accessToken);
      await Users.findOne({
        where: { userId },
        attributes: { exclude: ["password"] },
      }).then((user) => {
        res.locals.user = user;
        next();
      });
    } catch (err) {
      res.status(401).send({ errorMessage: "로그인 후 이용 가능합니다." });
    }
  } catch (err) {
    console.log(err);
    return res
      .status(400)
      .send({ errorMessage: "알 수 없는 에러가 발생했습니다." });
  }
};

 

VS Code Thunder Client에서 cookie를 헤더에 보내는 방법


 

1. respose header에 서버가 클라로 날린 set-cookie의 값 (accessToken=~~~~~/, refreshToken=~~~~~~/)을 복사한다.

 

2. thunder client 메뉴 바에서 Env 탭 > cookie를 클릭한다.

 

3. 아까 위에서 로그인 하면서 만든 토큰 값(set-cookie)을 환경 변수로 저장해준다.

  • 이때, 꼭 변수명을 cookie로 저장해야 한다.

 

4. 다시, thunder client 메뉴 바에서 Activity 탭을 클릭하고, api 테스트 화면으로 돌아온다.

 

5. Http Headers 탭으로 가서, header = cookie, value에 {{cookie}}라고 해주고, value 탭에 초록색 불이 들어오는 것을 확인해야 한다.

 

이렇게 설정하면 thunder client에서 heaer에 쿠키로 토큰 값을 담아 보내기 성공!

 

그런데, 저 쿠키값을 json 형식으로 받아 사용하려면, 꼭 cookie-parser 미들웨어를 설치하고, 라우터 동작 전에 cookie-parser를 불러 줘야 한다. 아래는 내 app.js 파일의 최상단 구성이다.

  • 터미널에서 아래 명령을 입력해 cookie-parser미들웨어를 다운로드 한다.
npm i cookie-parser
  • app.js 파일 상단에 아래 코드를 넣어서, 미들웨어를 동작시킨다. 이때, 반드시 cookie-parser를 이용하는 router 미들웨어 위에 쿠키파서 미들웨어 동작 명령을 넣어 줘야 한다. 
    • 미들웨어는 선언한 순서대로 동작하기 때문에!!
    • 그러니까 항상 최상단에 필요한 모든 미들웨어를 선언해두고 가자.

미들웨어 동작 방식

const express = require("express");
const app = express();
const cookieParser = require("cookie-parser");

app.use(cookieParser());