리프레시 토큰의 필요성
리프레시 토큰은 왜 필요한가?
그것이 액세스 토큰과 리프레시 토큰을 알아보면서 드는 생각이었다.
대표적으로 알려진 리프레시 토큰을 이용함으로써 얻을 수 있는 이점은 다음과 같다.
- 리프레시 토큰의 유효기간을 길게 주게 되면서, 액세스 토큰의 유효기간을 줄일 수 있어 액세스 토큰이 탈취되어도 위험성이 줄음
- 액세스 토큰의 유효기간을 줄여도 리프레시 토큰으로 재발급하면서 짧은 주기로 로그인할 필요가 없어짐
먼저, 첫번째로 든 의문점은 왜 리프레시 토큰이 더 안전하게 뺏길 일이 없는가였다.
리프레시 토큰을 안전하게 보관할 수 있다면, 그것은 액세스 토큰도 가능할 것이다.
둘은 사실상 같은 토큰이고, 안에 담고 있는 내용만 다를 뿐이다.
그렇기에 왠만해선 한쪽이 뺏기면 나머지도 자연스럽게 뺏기기 쉽다고 생각했고, 이러면 굳이 재발급을 해가면서 더 서버의 자원을 소모시켜야는가 싶었다.
리프레시 토큰도 뺏기면 결국 리프레시 토큰의 유효기간만큼 해커한테 넘어가는 것은 똑같기 때문이다.
두번째 의문은 리프레시 토큰을 사용하면 짧은 주기로 로그인할 필요가 없다는 점이다.
두번째는 재발급의 자동화가 가능하다는 것인데, 이는 사실 액세스 토큰만으로도 구현이 가능하다.
액세스 토큰의 재발급이 필요한 시점에 액세스 토큰의 유효성을 체크하고, 새로 발급만 해주면, 사실 다를 바가 없다.
여기서 잘 생각해보고, 더 정보를 모아보니 첫번째 의문은 해결할 수 있었다.
먼저, 첫번재는 액세스 토큰과 리프레시 토큰의 노출 빈도에 정답이 있었다.
기본적으로 액세스 토큰은 서버에 요청을 보낼 때, 대부분 사용을 하게 된다. 반면, 리프레시 토큰은 오직 재발급 시점에만 사용이 된다.
오직 하나의 토큰만으로 재발급 여부를 결정한다면, 어떤 요청 시점에서 탈취된 토큰으로 재발급이 가능하다.
반면, 토큰을 둘로 나누어, 검증 과정에 리프레시 토큰과 액세스 토큰을 모두 필요로 한다면 어떤 요청 시점에 탈취된 액세스 토큰만으로는 검증이 불가능하며, 클라이언트가 재발급하는 시점에 네트워크로 리프레시 토큰을 탈취해야 재발급이 가능해진다는 것이다.
즉, 리프레시 토큰의 사용은 적어도 네트워크에서의 보안 강화로 이어지는 것이다.
쿠키를 서버에서 지정하여 httponly 등 보안 강화를 하면 브라우저에서 request 시에 자동으로 전송된다는 점 때문에 순간 다시 의문이 들었으나, 이는 쿠키의 path 설정을 간과한 문제여서 큰 문제는 아니었다.
애초에 쿠키 자체가 request 시에 자동으로 서버로 전송되나, httponly 옵션을 주면 자바스크립트 단계에서 접근이 불가능하여, xss 공격에 내성이 생기는 것이다.
로컬스토리지의 경우 xss 공격에 더 취약한 편이니, 이런 점에서 서버 측에서 httponly 옵션과 path를 사용하여 특정 링크(재발급)로만 쿠키가 전송되도록 하는 것이 제일 안전한 방법인 것이다. 물론 서버 메모리나 db에 저장하면 더 안전하겠지만, 그 순간 이미 세션의 개념으로 취급해야 한다고 봐야기 때문에, jwt 토큰 방식만의 장점을 취하면서 제일 안전한 것은 옵션을 적절하게 설정해놓은 쿠키라고 볼 수 있을 것이다.
또한, 위에서 다루진 않았지만 리프레시 토큰의 사용은 액세스 토큰의 보안 강화로 이어질 수 있다.
리프레시 토큰을 사용한다면, 액세스 토큰을 로컬 변수에 저장할 수 있게 된다.
기존에 토큰 하나로 모든 걸 처리하려 할 때, 토큰을 로컬 변수에 저장한다면, 새로고침했을 때, 토큰이 사라져, 로그인을 유지할 수 없게 된다.
하지만, 리프레시 토큰을 사용하면, 액세스 토큰을 재발급 받게 하여, 로그인을 유지시킬 수 있고, 이에따라 xss 공격과 csrf 공격에 좀 더 안전해질 수 있다.
로컬 변수의 경우 xss 공격과 csrf 공격으로 탈취하기가 더 어렵기 때문이다.
물론, 이 경우는 새로고침할 때마다 서버에 부하가 많이 가는 점을 고려해야 한다.
리프레시 토큰에 이 이상의 장점이 있을 수도 있겠으나, 아직 내가 알 수 있는 것은 이 정도뿐인 것 같다.