Refresh Token을 사용하는 이유
보안 문제
Access Token은 브라우저(쿠키, 로컬 스토리지 등)에 저장하기 때문에 언제든지 탈취당할 가능성이 있다고 한다. 이러한 보안 문제점 때문에 대안으로 나온 개념이 Refresh Token이다.
Access Token의 유효기간을 짧게 설정하고, Refresh Token의 유효기간을 길게 잡아서 리소스에 접근할 때는 Access Token을 통해서 하고 Access Token의 유효기간이 만료되면 Refresh Token으로 Access Token을 재발급받는 형태의 메커니즘이다.
이런 식으로 리소스 접근을 위한 Access Token의 유효기간을 짧게 설정함으로써 Access Token을 탈취당했을 때 짧은 시간 동안에만 피해가 발생하도록 하는 방법인 듯하다.
즉, 어쨌든 간에 Access Token의 탈취를 완전히 막을 순 없지만 탈취당했을 때의 피해 시간을 줄일 수 있다는 것 같다.
로그인 유지
Access Token이 탈취당했을 때 발생하는 피해를 줄이기 위해 토큰의 유효기간을 짧게 줄여버리면 사용자는 만료될 때마다 매번 다시 로그인해야 한다는 문제점이 생긴다. 만약 게시판 서비스라고 한다면, 사용자가 글을 쓰고 있는 와중에 Access Token의 만료 기간이 지나버릴 수 있을 것이다. 그리고 만료되고 난 후에 글쓰기 완료 버튼을 눌러버리면 서버는 해당 토큰을 유효한 토큰이 아니라고 간주해서 정상적인 처리가 되지 않고 로그아웃 될 것이다.
이런 로그인 유지에 대한 방안으로 Refresh Token을 사용할 수 있다. 사용자가 글을 쓰는 와중에 Access Token이 만료되어도 서버에서 Refresh Token을 검증하고 Access Token을 재발급해주기 때문이다.
Refresh Token을 탈취당한다면?
Access Token의 만료기간을 짧게 설정해 놓음으로써 탈취당하더라도 피해 시간을 줄일 수 있다는 것은 이해했다.
하지만 결국 Refresh Token도 탈취당한다면 Access Token 하나만 사용하고 만료기간을 길게 잡아놓는 거랑 뭐가 다르지? 하는 의문점이 생겼고 여러 자료들을 찾아보면서 나름대로 생각을 정리해 봤다.
어쨌든 Access Token의 만료기간을 짧게 설정해 놓으면 피해 시간을 줄일 수 있으므로 토큰의 만료기간을 짧게 설정해 놓는다. 그리고 짧게 설정해 놓으면 자주 로그인해야 한다는 문제가 생기니 Refresh Token을 사용한다.
Access Token과 Refresh Token 두 개를 사용하면 Access Token만 탈취당했을 경우엔 피해 시간을 줄일 수 있는 것이고,
Refresh Token을 탈취당한다면 답이 없다고 판단하기로 했다.
하지만 Refresh Token을 서버의 DB 혹은 Redis에 저장해 놓는다면 Refresh Token이 탈취되었을 경우 파기를 하는 등의 대처를 할 수 있는 여지가 생긴다.
그리고 Access Token은 서버에 무언가 요청을 할 때마다 네트워크 전송을 하지만 Refresh Token은 Access Token이 만료되고 재발급받는 시점에만 전송하도록 구성한다면 Access Token보다 네트워크를 통해서 탈취당할 확률이 훨씬 낮지 않을까 하는 생각을 해본다.
Access Token만 사용하던 Refresh Token도 같이 사용하던 둘 다 탈취당할 가능성은 존재하므로 HTTPS를 적용한다거나, 토큰을 쿠키에 저장하고 있다면 httpOnly와 secure 옵션을 적용한다거나 하는 등의 탈취당하지 않을 노력을 해야 된다는 생각을 갖게 되었다.
결론
여러 자료를 찾아보니 사람들 마다 Refresh Token에 대해서 생각하는 게 달랐다. 토큰 저장만 해도 클라이언트에만 저장, 클라이언트 + DB, 클라이언트 + Redis에 저장 등 다양했고 토큰 재발급 방법도 서버에서 직접 만료 시간을 체크하여 토큰을 재발급하여 응답해 준다거나, 만료되었다면 정상 응답을 해주지 않고 클라이언트에 재발급 요청을 하라고 한다거나 하는 등 정말 다양했다. 또한 만료 시간은 클라이언트에서도 체크가 가능하다며 서버에서 체크하지 않고 setInterval()을 사용하여 토큰이 만료되면 서버에 재발급 요청을 보내는 사람도 있었다. 아니면 API 요청 전에 항상 토큰이 만료되었는지 체크하고 만료되었다면 재발급 요청 후 다시 API를 요청한다.
사실 뭐가 더 좋고 나쁘고는 사용해보지 않아서 모르겠고 정답도 없는 것 같아서 프로젝트나 팀의 상황에 따라서 적절하게 택해야 하는 것 같다. 일단 이번 토이 프로젝트에서는 가장 끌리는 방식으로 택하고, 나중에 좀 더 자세하게 자료를 찾아보고 개선하는 방향으로 발전해나가고자 한다.