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);
}
);