
씨즌넷 프로젝트에서 내가 맡은 부분 중 VideoUpload에는 서버로 데이터를 보내기 때문에 Post를 사용하였다. 때문에 access token이 필요했는데, 우리 프로젝트는 jwt를 기반으로 refresh token rotation 방식을 사용한다는 이야기를 들었다. 그래서 정확히 어떤 방식인지 궁금해서 찾아보게 되었다.
JWT는 헤더(Header), 페이로드(Payload), 서명(Signature) 세 파트로 나누어져 있다.
JWT 기반 인증에서는 일반적으로 다음과 같은 흐름을 따른다.
하지만 이 방식에는 치명적인 보안 문제가 있다.
이 문제를 해결하기 위해 Refresh Token Rotation 방식을 사용할 수 있다.
즉, Refresh Token이 탈취되더라도 공격자는 재사용할 수 없다.
그래서 장점을 크게 세 가지로 말하자면
이 방식은 Auth0, Google OAuth 등에서도 많이 사용되는 방식이다.
씨즌넷 프로젝트는 API 호출을 효율적이고 일관되게 사용하기 위해 axios 인스턴스를 사용하였는데, 이런 부분들에서 Refresh Token Rotation이 사용되었음을 알 수 있다.
크게 요청 인터셉터와 응답 인터셉터로 나눌 수 있는데, 먼저 요청 인터셉터이다.
if (request?.status === 401 && !request._retry) {
// 아래 코드는 토큰 갱신이 완료되면 모두 새 토큰을 사용해 재시도하도록 함
if (refreshFlag) {
return new Promise(function (resolve, reject) {
failedQueue.push({ resolve, reject });
})
.then((token) => {
request.headers["Authorization"] = "Bearer " + token;
return SSIZENNET_API(request);
})
.catch((err) => {
return Promise.reject(err);
});
}
request._retry = true;
refreshFlag = true;
// refresh token을 가져와서 새 access token을 요청하는 코드(잠시 생략)
}
먼저 이 부분을 통해 401 에러를 반환할 경우 재시도 플래그를 확인하여 토큰 갱신 과정을 진행함을 보여준다.
중간의 코드는 이미 토큰 갱신이 진행 중일 때, 다른 요청들을 failedQueue에 넣어 새로운 토큰이 발급되면 모두 함께 재시도할 수 있도록 큐에 저장하는 역할을 한다.
다음은 응답 인터셉터이다.
const res = await axios.post(`${data_api}/auth/refresh`, {
refresh: refresh_token,
});
const accessTokenValue = res.data["acess"];
const refreshTokenValue = res.data["refresh"];
sessionStorage.setItem("access-token", accessTokenValue);
sessionStorage.setItem("refresh-token", refreshTokenValue);
SSIZENNET_API.defaults.headers["Authorization"] = `Bearer ${accessTokenValue}`;
request.headers["Authorization"] = `Bearer ${accessTokenValue}`;
processQueue(null, accessTokenValue);
refreshFlag = false;
return SSIZENNET_API(request);
이 코드는 위에서 생략한 토큰 갱신 및 업데이트 기능을 하는 코드인데, refresh token을 사용하여 새로운 access token 및 refresh token을 받아서 sessionStorage와 기본 헤더를 업데이트한 후, 대기 중인 모든 요청(failedQueue)을 새 토큰으로 재요청하는 로직이다.
나는 accesstoken을 직접 env 파일에 입력하는 방식으로 코딩하여서 하드 코딩을 한다고 생각했는데, axios 인스턴스 속에서 이렇게 복잡한 Refresh Token Rotation 로직이 작동되고 있다는 것을 알고 나니 놀라웠다. 코드 하나하나 뜯어보며 공부하는 것의 중요성을 느꼈고, 더 많은 CS 지식을 익히고 싶다는 생각이 들었다.
고생했습니다 코드분석도 잘했고 느낀 점이 너무 맘에드네요 앞으로도 많은 공부를 하고 많은 코드를 보면서 성장하길 기대할게요:)