토큰을 사용하면 서버에 사용자의 상태를 저장하지 않는다는 장점이 있는 반면 공격자가 토큰을 탈취한 경우 토큰을 즉시 무효화시키지 못하는 보안 취약점을 가집니다. 이를 방지하고자 토큰의 유효시간을 짧게, 즉 만료시간을 생성시간에서 얼마 지나지 않은 시간으로 설정할 수 있습니다. 하지만 이 방법은 만료된 토큰으로 들어온 요청을 무시하고 다시 사용자에게 로그인 정보를 입력하게 할 수 밖에 없습니다. 사용자가 페이지를 이동하거나 어떤 동작을 수행하려 할 때마다 로그인을 해야 한다면 아무도 그 서비스를 사용하려 하지 않을 것입니다.
비상태저장 방식인 토큰의 보안 취약점을 보강하고 사용자 편의성을 유지하기 위해 슬라이딩 세션을 사용합니다. 슬라이딩 세션은 로그인 정보를 다시 입력하지 않고 현재 가지고 있는 토큰을 새로운 토큰으로 발급하는 방식을 말합니다.
그렇다면 사용자가 로그인하는 과정을 대신해 줄 무언가가 필요한데 이를 리프레시 토큰(Refresh Token)을 사용하여 해결합니다. 리프레시 토큰은 액세스 토큰과 마찬가지로 JWT를 사용할 수 있고 액세스 토큰에 비해 긴 만료시간을 가집니다. 처음 사용자가 로그인 할 때 액세스 토큰과 함께 리프레시 토큰을 발급하고, 클라이언트는 액세스 토큰 만료로 에러가 발생한 경우 리프레시 토큰을 이용하여 새로운 액세스 토큰을 발급해 달라는 요청을 합니다. 마찬가지로 리프레시 토큰 만료로 다시 리프레시 토큰을 발급받고자 하는 경우에도 가장 최근에 발급한(클라이언트는 항상 최신 리프레시 토큰만 가짐) 리프레시 토큰으로 새로운 토큰을 발급받습니다.
리프레시 토큰이 탈취된다면 액세스 토큰보다 더 오랜 기간 보안에 구멍이 생기기 때문에 클라이언트는 반드시 안전한 공간에 저장해야 합니다. 액세스 토큰과 리프레시 토큰의 만료기간을 얼마로 할 지는 서비스마다 사용자의 패턴을 보고 적당한 기간으로 설정하면 됩니다. 액세스 토큰을 5분 미만으로 짧게 가져가는 경우도 있고, 24시간으로 설정하는 경우도 있습니다. 리프레시 토큰 역시 한 달 이상으로 하는 경우가 많지만 6개월 또는 아예 만료하지 않도록 하는 경우도 있습니다. 이 때는 토큰을 암호화하고 암호화 키를 저장하는 등의 별도의 보안장치를 마련해야 할 것입니다. 아예 트래픽이 외부로 나가지 않는 내부 망에서 사용할 수도 있겠습니다.
리프레시 토큰은 보통 서버의 DB에 저장해 두고 요청에 포함된 리프레시 토큰과 비교합니다. 비상태저장방식의 장점이 약화되기는 했지만 뒤에서 설명하겠지만 이렇게 해야만 하는 이유가 있습니다. 비상태저장과 보안성, 사용성을 위해 타협한 방식이라 하겠습니다.
리프레시 토큰 발급 전략
액세스 토큰은 유효기간이 남은 토큰을 여러개 발급해서 사용할 수 있습니다. 하지만 리프레시 토큰은 서비스 실행중에 유일하게 다루어져야 합니다. 리프레시 토큰은 만료기간이 길고 액세스 토큰을 언제든지 다시 얻을 수 있기 때문에 새로운 리프레시 토큰을 발급했을 때 이전에 발급한 토큰이 유효하지 않도록 해서 탈취된 토큰이 비록 만료기간이 남아 있다 해도 비정상 토큰으로 인지할 수 있도록 해야 합니다. 이를 위해 DB에서 이전 토큰을 지울 수도 있겠지만 리프레시 토큰을 DB에 영속화 시키고 유효하지 여부를 따지는 필드를 따로 둘 수 있습니다. 이렇게 하면 공격자가 무작위로 리프레시 토큰을 생성했는지 아니면 과거에 유효하게 발급되었던 토큰이 실제 사용되고 있는지 알 수 있습니다. 만약 전자라면 공격자의 IP를 차단하는 등의 조치만 취하면 되지만 후자의 경우는 사용자에게 토큰이 탈취되었다는 알림을 줄 수도 있겠습니다. 서비스를 어떻게 구성할 지 원하는 방식을 택하면 되겠습니다.
리프레시 토큰이 탈취되었을 때
리프레시 토큰이 탈취되었다는 것을 알게 된 경우, 즉 서버에 저장되어 있는 이전에 발급한 리프레시 토큰이 사용되었을 때는 현재 유효한 리프레시 토큰도 무효화 시켜야 합니다. 이유는 공격자가 유효한 리프레시 토큰을 이용해서 새로운 리프레시 토큰을 발급하고, 이후 사용자가 자신이 발급받은 원래는 유효했던 리프레시 토큰을 사용하는 경우 공격자의 리프레시 토큰을 무효화시켜 더 이상 사용하지 못하도록 해야하기 때문입니다. 그래서 유저가가 다시 로그인을 통해 토큰을 발급받을 수 있도록 해야 합니다.
추가로 일반적인 서비스 유저에게는 제공되지 않겠지만 OAuth Client를 위해 리프레시 토큰이 탈취된 것을 알게 되었을 경우 유저가 직접 리프레시 토큰을 삭제할 수 있는 방안이 함께 마련되면 좋습니다.
'Tips > 인증 인가' 카테고리의 다른 글
인증(Authentication) vs. 인가(Authorization) (0) | 2021.11.14 |
---|---|
JWT (JSON Web Token) (0) | 2021.11.06 |