⛵ 항해99/TIL · WIL ✏️

[TIL] 2023.11.08 - JWT Access Token / Refresh Token 구현

hhhhy 2023. 11. 9. 23:53

 JWT Access Token / Refresh Token 구현 

  • axios interceptors를 사용해 axios가 서버로 HTTP 요청을 보내기 전, refresh Token으로 만료된 access Token을 재발급 받도로록 구현
// accessToken 재발급
axiosInstance.interceptors.response.use(
  (response) => {
    return response;
  },
  async (error) => {
    // 액세스 토큰 만료됐을 때,
    if (error.response.data.status === 500) {
      const refreshToken = getCookie("refreshToken"); // 리프레시 토큰 가져오고,
      localStorage.removeItem("accessToken"); // 엑세스 토큰은 지우기(axiosInstance 기본설정 때문에 post 보낼때 같이 보내지는데, 403 에러남!)

      // console.log("액세스 토큰 만료", error);
      // console.log("refreshToken 있니?", refreshToken);

      // 1. 리프레시 토큰이 있으면,
      if (refreshToken) {
        try {
          // 재발급 API로 리프레시 토큰 보내서
          const response = await axiosInstance.post(
            "/api/token/refreshAccessToken",
            null, // 요청 body 보내지 않음
            {
              headers: {
                Authorization_refresh: refreshToken,
              },
            }
          );
          // console.log("리프레시 있을 때 response", response);

          // 새로운 토큰(액세스/리프레시) 받고, 저장하기
          const newAccessToken = response.data.accessToken;
          const newRefreshToken = response.data.refreshToken;
          localStorage.setItem("accessToken", newAccessToken);
          setCookie("refreshToken", newRefreshToken, {
            path: "/", // 모든 페이지에서 쿠키 접근 가능
            secure: true, // https로 통신할때만 쿠키 저장됨
            // httpOnly: true, // HttpOnly 속성을 적용(js 접근 불가) > 클라이언트에서 저장안됨
          });

          error.config.headers["Authorization"] = newAccessToken; // 업데이트된 액세스 토큰을 헤더에 설정하고 현재 요청을 다시 실행
          return axiosInstance(error.config); // 현재 요청을 새로운 액세스 토큰을 가지고 재시도

          // 2. 리프레시 토큰 에러면,
        } catch (refreshError) {
          // console.log("리프레시 에러 refreshError", refreshError);
          // 토큰(액세스/리프레시) 지우고, 재로그인 시키기
          localStorage.removeItem("accessToken");
          removeCookie("refreshToken");
          window.location.href = "/login";
          alert("재로그인이 필요합니다.");
        }
      } else {
        // 토큰(액세스/리프레시) 지우고, 재로그인 시키기
        localStorage.removeItem("accessToken");
        removeCookie("refreshToken");
        window.location.href = "/login";
        alert("재로그인이 필요합니다.");
      }
    }

    // 다른 오류의 경우, 오류를 다시 반환
    return Promise.reject(error);
  }
);