인후 서비스의 인증 시리즈는 아래 순서대로 진행돼요.
- 1편: (이번 편) Access Token과 Refresh Token 사용하기
- 2편: 중복 로그인 방지, 기기 제한 기능 도입하기
- 3편: E2E 테스트마다 독립적인 로그인 상태 유지하기
안녕하세요. 인후
개발자 민경찬입니다.
인후는 인하대 주변 상가 정보를 모아볼 수 있는 서비스예요.
이번 1편에서는 인후 서비스에서는 왜 Access Token과 Refresh Token을 사용하였는지 얘기해 볼게요.
Session 방식은 사용자의 로그인 상태와 관련 모든 정보를 서버가 관리하는 방식이에요.
클라이언트는 로그인 정보에 접근할 수 있는 Session ID를 보관하죠.
결국, 인증만을 위해 세션 스토리지를 의존하는 구조는 서버리스나 외부 컴포넌트가 많아지고 트래픽이 커질수록 네트워크·보안 설정 부담 때문에 인프라 유연성이 떨어진다고 느꼈어요.
세션 방식이 인프라 유연성에서 한계를 보인다면, JWT 방식이 좋은 대안이 될 것이라고 생각했어요.
세션 스토리지가 필요하지 않기 때문이였어요.
JWT는 로그인 상태를 서버에 저장하지 않고, 클라이언트가 토큰을 들고 다니며 인증하는 방식이에요.
무효활 방법이 없으니, Access Token의 만료 시간을 짧게 설정할 수밖에 없어요.
그 결과, 사용자는 자주 토큰을 갱신해야 하는 불편을 겪게 되죠.
또 한 가지 문제는, 서버가 토큰 상태를 전혀 들고 있지 않아서
로그인 기기 제한, 강제 로그아웃 같은 서버 주도 정책을 적용하기 어렵다는 점이에요.
하나의 JWT만을 사용하는 방식은 탈취 피해를 줄이기 위하여 만료 시간(TTL)을 짧게 가져가요.
하지만 이런 방식은 사용자가 토큰을 자주 갱신해야하는 불편이 생기죠.
이를 해결하기 위해, 두 가지 종류로 토큰을 나누었어요. 그것이 바로 Access Token과 Refresh Token이에요.
Refresh Token은 오직 Access Token을 재발급할 때만 사용하기 때문에, 네트워크 상에 노출될 가능성이 거의 없어 보안성이 높아요.
또한, TTL도 길어 로그인 유지를 오랫동안 할 수도 있어요.
프론트엔드에서 만료된 Access Token을 자동으로 재발급하고,
원래 요청을 재시도하는 로직은 별도 포스트에서 자세히 다룰 예정이에요.
Refresh Token만으로는 중복 로그인 제어나 로그인 기기 개수 제한 같은 서버 주도적인 인증 정책을 적용하기 어려웠어요.
이를 해결하기 위해, Session 방식 일부를 차용했어요.
발급한 Refresh Token을 서버 스토리지에 저장하는 방식이에요.
반대로 Access Token은 여전히 서버 스토리지와 독립적이에요.
모든 서버 컴포넌트는 Access Token의 서명과 만료 시간만 확인하므로,
인증을 필요로하는 모든 서버 컴포넌트는 토큰 스토리지를 필요로하지 않아요.
과정은 여전히 비슷해요.
로그인 할 때, 토큰 스토리지에 생성한 Refresh Token을 저장하죠.
Access Token을 재발급하는 로직도 크게 바뀌지 않아요.
재발급을 요청할 때 보낸 Refresh Token이 토큰 스토리지에 존재하는지 확인할거에요.
이제, 서버 주도 정책 중 하나인 강제 로그아웃을 가정해볼게요.
서버는 토큰 스토리지에서 강제 로그아웃 하려는 Refresh Token을 삭제해요.
이후 이 사용자가 해당 Refresh Token으로 Access Token 재발급을 요청하면,
스토리지에서 토큰을 찾을 수 없으므로 재발급이 거부되고, 로그인 상태가 종료돼요.
JWT는 Base64로 인코딩만 되어 있어, 누구나 토큰을 디코드하여 페이로드 내용을 확인할 수 있어요.
따라서 Access Token과 Refresh Token 안에는 비밀번호나 예민한 개인정보는 절대로 넣으면 안돼요.
인증과 권한 검증에 필요한 최소한의 정보만 담아야 해요.
Access Token은 서명과 만료 시간만으로 유효성을 판단해요.
그래서 Refresh Token이 무효화되어도 발급된 Access Token은 TTL이 끝날 때까지 유효해요.
팀에서는 이 기간을 Access Token의 잔여 유효시간이라 부르고 있어요.
Acess Token의 TTL을 짧게 설정하면
Access Token의 TTL을 길게 설정하면
TTL은 보안과 서버 부하 사이에서 균형을 맞춰 설정해야해요.
다음 편에서는 Redis를 사용하여 토큰 스토리지를 설계하고
토큰 탈취를 감지하는 방법에 대해서 얘기해볼게요.
읽어주셔서 감사합니다.
선 추천 후 읽기