모카스터디/ETC 개발 지식

리프레쉬 토큰을 왜 사용하는가 ?

softmoca__ 2024. 3. 3. 22:08
목차

https://softmoca.tistory.com/294

 

세션, 쿠키, JWT 토큰 및 인증과 인가 개념 정리

로그인기능을 구현한는 것도 어렵지만 무엇보다 로그인 상태를 '유지'하는거도 만만치 않게 어려운 일이다. 예로 들어 naver에 로그인을 했을 때 메일함을 들어가고 나올때, 보낸 메일함과 받은

softmoca.tistory.com

전반적인 세션과 jwt토큰에 대한 인증 인가 개념은 위 포스트에 정리하였다.

 

리프레쉬 토큰을 왜 사용하는가 ?

가장 보편적으로 리프레쉬 토큰이 사용되는 이유는 아래와 같다.

서비스에서 특정 권한이 있는 사용자만 보낼수 있는 api가 있다.

예를 들면 게시글 삭제 혹은 사용자 정보 수정, 관리자 페이지 접속 등등

 

프론트엔드에서 사용자가 로그인을 하면 백엔드에서 엑세스 토큰과 리프레쉬토큰을 반환해 준다.

그리고 그 토큰을 프론트엔드의 저장소(쿠키or 로컬스토리지 등등)에 저장을 해두고 권한이 필요한 api요청을 할시 헤더에 같이 로그인시 받급 받은 엑세스 토큰을 동봉하여 보낸다.

그리고 백엔드 단에서 해당 요청의 헤더에 있는 토큰을 검증하여 유효한 권한을 가진 사용자라면 요청에 대한 응답값을 보내준다.

 

하지만 엑세스 토큰이 토큰이 해커에게 탈취 당했을 시 해당 토큰으로 해커가 다른 사용자 처럼 api를 보내어 악용할 수 있다.

이러한 피해를 최소화 하기 위해 엑세스 토큰의 유효기간을 짧게(약 5분) 두고 유효기간이 긴 리프레쉬 토큰을 로그인시 같이 발급해서 유효기간이 짧은 엑세스 토근을 리프레쉬 토큰을 사용해 재발급 받게한다.

 

즉, 리프레쉬 토큰은 유효기간이 짧은 엑세스 토큰을 재발급 하기 위해 사용이 된다.

 

궁금점

하지만 어쨌든 프론트엔드에서 리프레쉬 토큰과 엑세스 토큰을 둘다 가지고 있는데 왜 굳이 엑세스 토큰만 탈취당한다고 가정을 하는가 ?

처음 이 생각이든 이유는 해커가 탈취하는 과정에서 왜 굳이 엑세스 토큰과 리프레쉬 토큰이 있는데 엑세스 토큰만 가져 간다는 것이다.

바닥에 5만원권 하나와 1만원권 하나가 있는데 1만원권만 가져 가는듯한...(?)

 

 

해당 궁금점과 찜찜함이 떠올랐을 때 나는 한가지 가능성 말곤 떠오르지 않았다.

프론트엔드에서 요청을 보내 서버로 가는 네트워크 과정상에서 탈취 가능성 가장 높아서..?

 

 

 

하지만 나의 주관적 생각 이어서 다른 확실한 레퍼런스를 참조해서 정리하고자 한다.

이를 위해서는 몇가지 요소를 고려해야한다.

 

 


탈취와 노출 위험
- 노출 빈도와 범위: 엑세스 토큰은 사용자가 권한이 필요한 API를 호출할 때마다 노출된다. 이는 리프레쉬 토큰에 비해 훨씬 빈번한 노출을 의미하며, 공격자가 탈취할 기회를 더 많이 제공합니다. 반면, 리프레쉬 토큰은 엑세스 토큰을 재발급 받을 필요가 있을 때만 사용되므로 노출 빈도가 훨씬 적습니다.

저장 방식의 차이
- 저장 보안성: 보안의 모범 사례에 따르면, 리프레쉬 토큰은 가능한 한 보안이 강화된 저장소에 저장해야 한다(예: HttpOnly 쿠키). 이는 리프레쉬 토큰이 자바스크립트 등의 클라이언트 사이드 스크립트를 통해 접근할 수 없도록 함으로써 XSS(교차 사이트 스크립팅) 공격으로부터 보호할 수 있다. 반면, 엑세스 토큰은 클라이언트 사이드에서 API 호출을 위해 직접 사용되므로, 보다 접근 가능한 형태로 저장될 필요가 있다.


결론적으로, 엑세스 토큰의 탈취 가능성이 더 높게 거론되는 이유는 그 빈번한 사용과 노출 때문이다. 그러나 실제로는 리프레쉬 토큰의 보안이 더 중요하며, 더 심각한 위협이 될 수 있다.

 

 

즉, '리프레쉬 토큰과 엑세스 토큰 모두 프론트엔드에 저장하고 관리하는 경우'에는 처음 노출 빈도와 범위가 잦고 넓은 엑세스 토큰의 탈취에 더 걱정하고 주의를 한다.

 

 

 

하지만 리프레쉬 토큰의 저장 범위를 프론트에만 국한 하지 않으면 해당 걱정의 범위는 줄어 든다.

예를 들어 (http only)cookie, local storage, session storage 혹은 데이터 베이스, redis등등 다양한 보안정책 상황에 맞게 저장을 할수 있다. 또한 refresh token 발행에 PKCE를 사용할 수도 있다.

즉, 클라이언트에게 제공되는 refresh token에 대한안전성은 늘 문제로 제기 될 수 있다. 그래서 refresh token을 어디에 저장할 것인지는 보안 정책 상황에 따라 다르다고 할 수 있다.

다만, access token의 안전성 확보를 위해 만료 시간을 짧게 잡았고 그것을 보완하기 위해refresh token이 생겼다는 사실은 기억하는게 좋을 것 같다.

 

 

 

 

 

 

+ 추가 궁금증

리프레쉬 토큰을 DB에 저장을 하게 되면 세션과 같이 DB를 갔다 와야하니 세션의 단점을 그대로 가진꼴이 되는게 아닌가 ?

리프레쉬 토큰을 데이터베이스에 저장하는 것은 세션과 유사한 기능을 제공할 수 있다. 그러나 몇 가지 차이점이 있다.

 

 

유효 기간 관리: 세션은 보통 서버 메모리에 저장되며, 클라이언트의 요청 간에 유지된다. 

반면에 리프레쉬 토큰은 데이터베이스에 저장되어 지속적으로 유지된다. 따라서 세션은 서버 메모리에 저장되어 있기 때문에 서버가 다시 시작되면 손실될 수 있지만, 리프레쉬 토큰은 데이터베이스에 저장되어 서버 재시작과 관계없이 지속적으로 유지될 수 있다.

다중 디바이스 지원: 세션은 일반적으로 특정 디바이스에 종속되어 있다. 따라서 다른 디바이스에서 동일한 세션을 공유하기 어렵다. 반면에 리프레쉬 토큰은 데이터베이스에 저장되어 있으므로 다양한 디바이스에서 동일한 인증 세션을 공유할 수 있다.

확장성: 리프레쉬 토큰을 데이터베이스에 저장함으로써 데이터베이스의 확장성을 높일 수 있다. 세션은 서버 메모리에 저장되기 때문에 서버 확장이 필요할 때 세션 관리에 어려움을 겪을 수 있다. 반면에 데이터베이스는 일반적으로 수평적으로 확장이 가능하므로 리프레쉬 토큰을 저장하는 데이터베이스도 확장 가능하다.

따라서 리프레쉬 토큰을 데이터베이스에 저장하는 것은 세션과 유사한 기능을 제공할 수 있지만, 몇 가지 차이점이 있어 이를 고려하여 어떤 방식을 선택할지 결정해야 한다.

 

 

 

 

 

 

 

 

결론 

모든 기술 스택에는 각자만의 장단점이 있어 해당 서비스에 맞게 고려하여 적용을 해야한다.

 

 

 

현재 내가 구현중인 서비스는 은행서비스 혹은 결제 서비스가 아닌 단순 sns서비스 플랫폼 이기 때문에 서버에 과부하를 감수할 만큼 과한 보안 대신 상대적으로 효율적인 방식으로 리프레쉬 토큰만 같이 발급하여  보안을 조금더 강화 하는 정도로 마무리 지어야겠다.

 

 

+ 차후 리프레쉬 토큰은 httponly쿠키, 레디스 혹은 DB에 저장을 하는 방식으로 고도화를 해봐야겠다.