인증, 인가 과정에서 많이 사용되는 방법이 몇개 있습니다.
그 중에서 jwt 토큰은 무상태성을 보장해주기 때문에 서버 확장에 장점이 있습니다.
하지만 토큰이 탈취된다면 상황은 달라집니다.
공격자도 해당 토큰을 사용하여 유저인 척, 인증 인가 과정을 통과할 수 있기 때문이죠.
그래서 토큰에는 보통 유효 기간을 두게 됩니다.
어떤 토큰의 유효 기간이 3분이면 그 토큰은 발행되고 3분이 지나면 사용이 불가능해지는 것이죠.
이제 공격자가 탈취를 해도 걱정은 좀 덜었습니다.
어차피 3분밖에 못쓰니까요.
유저는 유효 기간이 3분인 토큰을 발급받았습니다.
그리고 3분이 지나서 토큰이 만료되었습니다.
이제 유저는 토큰을 새로 발급받아야겠죠?
그러려면 로그인을 다시 해야 합니다.
유저가 3분마다 로그인을 해야하는 번거로운 일이 발생한 것이죠.
이 문제를 해결하는 것이 리프레시 토큰입니다.
리프레시 토큰은 액세스 토큰이 만료되었을 때 새로운 액세스 토큰을 발급받을 때 사용됩니다.
다음과 같은 과정을 통해 새로운 액세스 토큰을 발급받을 수 있습니다.

출처 : https://www.rfc-editor.org/rfc/rfc6749.html
보시다시피 액세스 토큰이 만료되면 리프레시 토큰을 통해 새로운 액세스 토큰을 발급받게 됩니다.
보통 액세스 토큰의 유효 기간은 짧게, 리프레시 토큰은 길게 발행하게 됩니다.
저희 팀은 원래 딱 위의 방식대로 진행하려고 했습니다.
하지만 리프레시 토큰이 탈취된다면 어떻게 될까요?
공격자가 리프레시 토큰의 유효 기간만큼 한도없이 액세스 토큰을 발행받아 계속 리소스에 접근할 수 있겠죠.
그래서 저희는 RTR(Refresh Token Rotation)이라고 하는 리프레시 토큰 탈취 감지 로직을 구현하기로 했습니다.
원리는 간단합니다.
리프레시 토큰을 한 번만 사용하게 하자. 만약 두 번 사용하려고 한다면 이건 탈취된 것이다.
공격자가 액세스 토큰1과 리프레시 토큰1을 탈취했다고 가정합시다.
공격자가 액세스 토큰1을 보냈는데 유효 기간이 짧아 금방 만료가 되었습니다.
그래서 리프레시 토큰1을 사용해 새로운 액세스 토큰2와 리프레시 토큰2를 발급받았습니다.
이때 유저도 마찬가지로 액세스 토큰1이 만료되었습니다.
유저가 새로운 액세스 토큰을 발급받기 위해 리프레시 토큰1을 서버로 보냅니다.
이때 서버는 탈취를 감지하게 됩니다.
리프레시 토큰1이 두 번 사용되었기 때문이죠.
먼저 리프레시 토큰이 두 번 사용되는 것을 확인하기 위해 가장 최신의 리프레시 토큰을 서버에 저장할 필요가 있습니다.
이러면 무상태성이 깨지게 되는 것이죠.
클라이언트의 리프레시 토큰을 서버에 저장하게 되니까요.
다음으로 유저가 리프레시 토큰1을 사용하지 않고 종료할 때 발생합니다.
이 리프레시 토큰1이 탈취되었기 때문에 공격자는 이걸 계속 쓸 것입니다.
하지만 유저는 종료했기 때문에 리프레시 토큰1을 사용하지 않습니다.
유저가 재접속하기 전까지 공격자가 계속 쓸 수 있는 것이죠.
이 문제는 액세스 토큰 만료 기한을 굉장히 짧게 가져감으로써 완화할 수 있기는 하지만 완벽하게 해결하기는 쉽지 않은 것 같습니다.