팝핀(Poppin) 프로젝트 회고


Refresh Token

서버와 클라이언트는 토큰을 주고 받으며 인증과 인가를 처리할 수 있다.

Refresh Token은 Access Token이 만료되었을 때, 새로 재발급 해주는 열쇠가 된다.

Access Token은 보통 짧은 만료 기간을 가지는 반면, Refresh Token은 상대적으로 긴 만료 기간을 가진다.

만약 Access Token이 긴 만료 시간을 가지게 되면, 탈취당하여 악의적인 공격에 사용될 수 있다.
포스트맨에서 API 테스트를 할 때 만료되지 않은 토큰을 헤더의 Authorization Bearer에 집어넣는다.

즉, API 명세를 알고 해당 토큰을 가지고 있는 누구나 필요로 하는 서버 자원을 가져올 수 있는 것이다.

이러한 토큰은 발급한 후 삭제가 불가능하고 만료 기간을 설정해서 해당 만료 시간이 지나야 무효화된다.
따라서 Access Token의 만료 기간을 짧게 유지하고, 상대적으로 긴 만료 시간을 가지는 Refresh Token을 통해

Access Token을 재발급 받음으로서 사용자가 로그아웃 없이 로그인 상태를 유지할 수 있게 한다.

 

기존에는 Access Token이 만료되면, Refresh Token을 확인하고

만료 기한이 지나지 않았다면 Access Token을 재발급 해주는 방식이었다.

시간이 지나 Refresh Token 또한 만료되면, 자동 로그아웃이 되며

다시 로그인을 했을 때 Access Token과 Refresh Token을 발급해준다.

Refresh Token Rotation(RTR)

RTR은 Access Token이 만료될 때마다 Refresh Token도 함께 교체를 해주는 것이다.

그렇게 되면 일회성 Refresh Token이 된다.
구체적인 플로우는 다음과 같다.

  1. 사용자가 로그인하면 서버는 Access Token과 Refresh Token을 발급한다.
  2. Access Token이 만료되면 클라이언트는 Refresh Token을 사용해 새로운 Access Token을 요청한다.
  3. 서버는 새로운 Access Token과 새로운 Refresh Token을 발급하고, 이전 Refresh Token을 무효화한다.
  4. 만약 탈취자가 이전 Refresh Token을 사용하려고 시도하면, 이미 무효화되었기 때문에 접근이 거부된다.

그렇다면 Refresh Token을 주기적으로 교체함으로써 보안이 강화되는 이유는 뭘까❓

  • Refresh Token을 짧은 시간 내에 회전시키기 때문에 탈취되더라도 사용 가능한 기간이 매우 짧다.
  • 이전 Refresh Token이 사용되면 새로운 토큰이 발급되고, 이전 토큰은 즉시 무효화되므로 재사용이 불가능하다.

💻 다음은 Refresh Token Rotation의 서버 로직이다. 코드를 일부 생략했다.

@Transactional
public JwtTokenDto refresh(String refreshToken) {
// 생략
Long userId = jwtUtil.getUserIdFromToken(token);
User user = userRepository.findById(userId)
.orElseThrow(() -> new CustomException(ErrorCode.NOT_FOUND_USER));
if (!user.getRefreshToken().equals(token)) {
throw new CustomException(ErrorCode.INVALID_TOKEN_ERROR);
}
JwtTokenDto jwtToken = jwtUtil.generateToken(userId, user.getRole());
user.updateRefreshToken(jwtToken.refreshToken());
return jwtToken;
}

카카오톡은 어떻게 자동 로그아웃을 방지하고 무한 로그인을 유지할 수 있을까❓❓

이는 카카오톡이 RTR 방식을 사용하여 Refresh Token을 주기적으로 교체하면서도 사용자가 로그아웃되지 않도록 하기 때문이다.

사용자는 마치 무한히 로그인된 상태를 유지하는 것처럼 보이지만,

실제로는 보안이 강화된 상태에서 토큰이 지속적으로 갱신되고 있는 것이다.

 

예상되는 문제점

Refresh Token Rotation(RTR) 방식의 도입으로 인해 Access Token 재발급 요청이 빈번해질 수 있다.

이는 사용자가 로그인할 때마다 Refresh Token이 교체되고,

그에 따라 서버는 새로운 Access Token과 Refresh Token을 발급하며 이전 토큰을 무효화해야 하기 때문이다.

이러한 과정에서 서버에 부하가 증가할 가능성이 있다.

특히, 많은 사용자가 동시에 서비스를 이용하는 경우, 서버는 연속적인 요청 처리로 인해 과부하 상태에 도달할 수 있다.

 

추가적으로 구현을 해보아야 할 영역

애플리케이션 서버와 인증 서버를 분리하는 방법으로 예상되는 문제점을 해결할 수 있을 것 같다.

인증 서버를 Redis와 같은 인메모리 저장소와 연동하는 방안을 고려할 수 있다.

이렇게 된다면 인증 요청에 대한 처리 부담을 애플리케이션 서버에서 분리하여 과부하도 방지할 수 있다.

또한 Redis는 데이터 조회 & 쓰기 속도가 빨라 지연 시간 감소를 보장할 수 있다.

하지만 그 만큼 인프라가 추가되는 것이니 비용이 증가하겠지...?

 

결론

Refresh Token Rotation은 보안 강화와 사용자 편의성을 모두 충족시키는 강력한 방법이다.

토큰 탈취의 위험을 최소화하면서도 사용자가 로그아웃 없이 지속적으로 서비스를 이용할 수 있게 된다.

사용자는 매번 로그인 시도를 할 필요 없이 무한 로그인 상태를 경험할 수 있다.

이를 통해 보다 안전하고 편리한 사용자 경험을 제공할 수 있다.


reference

https://auth0.com/docs/secure/tokens/json-web-tokens

'project > poppin-server' 카테고리의 다른 글

개발계 Jar 파일 배포 에러 - no main manifest attribute  (0) 2024.09.07
@Transactional 최적화  (0) 2024.08.03
조원준입니다