본문 바로가기
sns 프로젝트

token 검증 실패시 에러처리하기(토큰검증 미들웨어)

by 우주속공간 2024. 1. 21.

 

문제 발생

기존의 코드에서는 API가 실행되기 전에 토큰이 유효한지 검사하고, 그 결과를  받아서 결과에 따라 처리되었다. 

 

=> 하지만 이렇게 하니까 중복되는 코드 발생

 

기존의 코드 

router.post(
  "/",
  verifyAccessToken,
  verifyRefreshToken,
  async (req: any, res: Response, next: NextFunction) => {
//아래의 부분 반복
    if (req.token === "login again") {
      res.json("login again");
    } else if (req.token === "refresh ok") {
      await Follow.create({
        user_id: req.body.user_id,
        follower_id: currentUser,
      }).then((result) => {
        res.status(201).json(result);
      });
    }
  }
);

 

⇒ 에러발생이 발생했을때 미들웨어 코드에서 미리 끝내주지 않으면, 그 미들웨어를 사용할때마다 그다음 코드에서 에러에 대한 처리를 반복적으로 해주어야한다.

⇒ 즉 코드가 계속 중복된다는 뜻이다. 따라서 이를 방지하기위해서 토큰 검증 미들웨어 코드에서 끝낼 필요가 있다.

 

해결과정

 

📄 refresh token 검증 미들웨어 수정

 

=> catch에 req.token = “login again” 대신 return res.status(500).send({ message: "login again" }) 넣어줌

try {
    jwt.verify(token, process.env.REFRESH_TOKEN_SECRET);
    req.token = "refresh ok";
    req.email = decoded.email;
  } catch (error: any) {

    return res.status(500).send({ message: "login again" });
  }
  next();

⇒ refreshToken이 만료되면 서버에서 500번 에러를 던져주는데 이 경우 클라이언트 요청이 거부되기때문에 res.status(500).send({ message: "login again" }) 이부분도 실행 안됨.

 

📄 access token 검증 미들웨어

 

=> return res.status(419).json({code: 419,message: "토큰이 만료되었습니다.",}); 넘겨줌.

accessToken이 만료되면 그 다음 코드로 넘어가지 않는다

try {
    let decoded = jwt.verify(token, process.env.ACCESS_TOKEN_SECRET);
    console.log(token);
    req.email = decoded.email;
    console.log(decoded);
  } catch (error: any) {
    return res.status(419).json({
      code: 419,
      message: "토큰이 만료되었습니다.",
    });
  }
  next();

 

 

axios interceptor에 status번호에 따라서 에러 처리 (프론트)

function (error: any) {
    console.log(error.response.data);

    console.log(error.response.status);

    if (error.response.status === 419) {
      console.log("재발급 필요");
      customAxios.get("/refreshTokenRequest").then((res) => {
        window.alert("엑세스토큰 재발급 완료");
      });
    }

    if (error.response.status === 500) {
      console.log("로그인이 만료되었습니다");
      alert("재로그인 필요");
      dispatch(changeState(false));
      const navigate = useNavigate();
      navigate("/");
    }
  }

 

 

코드를 수정하면서 발견한 문제점

  • axios요청을 할때 header에 들어가는 accessToken이 업데이트가 안됨,
let accessToken = cookie.load("accessToken");

const customAxios = axios.create({
  baseURL: "<http://localhost:1234/>",
  headers: {
    Authorization: `Bearer ${accessToken}`,
  },

⇒ 처음 accessToken을 쿠키에서 가져온다음 요청을 보낼때마다 같은 토큰만 보냄. 업데이트가 안됨.

customAxios.interceptors.request.use(
  function (config) {
  
    // 요청 바로 직전
    // axios 설정값에 대해 작성합니다.
    
    let accessToken = cookie.load("accessToken");
    if (accessToken) {
      console.log(accessToken);
      config.headers.common["Authorization"] = `Bearer ${accessToken}`;
    }
    return config;
  },
  function (error) {
    console.log(error);
    // 요청 에러 처리를 작성합니다.
    return Promise.reject(error);
  }
);

⇒ 요청 직전에 accssToken을 받아와서 토큰이 업데이트되어도 바뀐 값이 header에 담김.

 

하나하나씩 console.log를 찍어보면서 데이터가 제대로 업데이트되고 있는지, 제대로 전송되고 있는지 확인하는게 중요하다는 것을 느낌.