20241218 TIL : Refresh Token과 Redis

MCS·2024년 12월 18일

TIL

목록 보기
27/45

오늘 학습한 내용

  • Refresh Token과 Redis
    • Access Token과 Refresh Token
    • Refresh Token Rotation(RTR)
    • 왜 Redis에서 Refresh Token을 관리할까?

Refresh Token을 Redis로 관리하기

Access Token과 Refresh Token

지금까지 JWT 토큰(Access Token)을 발행해서 로그인을 수행했는데, 이 Access Token만을 사용하는 방식에는 문제점이 여러가지 있다.

토큰이 만료될 때마다 다시 로그인해야 한다

Access Token의 유효기간이 만료되면 다시 로그인을 해야 하며, 사용자가 서비스 이용 중이었다면 불편함을 느낄 수 있다. 그렇다고 해서 유효기간을 길게 설정하면 문제가 생긴다.

토큰이 탈취당하면 대응할 방법이 없다

Access Token이 탈취당했을 때, 서버 측에서 대응할 수 있는 방법은 없다. 이런 상황에서 유효기간마저 길게 설정되어 있다면...
그래서 보통 유효기간을 짧게 설정하는데, 유효기간이 짧으면 또 사용자가 불편해지는 문제가 발생한다.

이런 문제들을 해결하기 위해 Access Token 재발급을 위한 Refresh Token을 사용한다.
Access Token을 통해 인증을 진행하고 만약 해당 토큰이 만료되었다면 Refresh Token을 보내어 Access Token을 재발급받고 그 토큰으로 다시 인증을 진행하게 된다.
Access Token의 유효기간은 짧게 설정하고, Refresh Token의 유효기간은 길게 설정한다.

(출처 : https://velog.io/@mj3242/Spring-Redis-활용-access-Token-refresh-Token-인증인가-구현)

다만 이 역시 문제점이 있다. jwt 토큰을 이용한 인증 방식은 stateless이기에 여전히 토큰 탈취에 대응할 수 있는 수단이 없다. Refresh Token을 탈취당할 경우, 만료되기 전까지 해커는 Access Token을 무한정 발급받을 수 있다.
이를 해결하기 위해 사용하는 방법 중 하나가 Refresh Token Rotation(RTR) 방식이다.

Refresh Token Rotation(RTR)

RTR 방식은 Access Token을 재발급할 때, Refresh Token도 함께 재발급하는 방식이다.
서버가 Refresh Token을 발급할 때 DB에 refresh token을 저장해 놓고, Access Token을 재발급할 때, Refresh Token도 함께 재발급하며 이를 DB에 반영한다.

사용자가 Access Token 재발급을 위해 Refresh Token을 보내면, 유효성을 검증하고 이것이 DB에 저장된 토큰과 일치하는지 확인한다.

이 방법이 Refresh Token 탈취에 대해 안전한 이유는?

탈취자가 refresh token을 탈취했다고 가정하자. refresh token을 탈취 당한 상태에서 유저가 계속 인증이 필요한 요청을 보내고 있었다고 하자. 그러면 access token이 만료될 때마다 계속 refresh token이 갱신될 것이다.
이 때 탈취자가 access token을 재발급 받기 위해 refresh token을 보낸다면, 이 토큰은 이전의 토큰이므로 DB에 더 이상 존재하지 않을 것이다.
따라서 이를 악의적인 공격으로 간주하고 refresh token을 DB에서 삭제 후 재로그인을 요구하는 응답을 줄 것이다.

만약 탈취자가 refresh token을 발급받고 유저보다 먼저 access token을 재발급받으면 어떻게 될까? DB에 refresh token이 갱신되고 진짜 유저는 옛날 refresh token을 가지고 있을 것이다. 이 때 진짜 유저가 다시 refresh token을 보내면 DB 저장 토큰과 다르기 때문에 악의적인 공격으로 간주하고 refresh token을 DB에서 삭제한 후 다시 로그인을 요구할 것이다. 진짜 유저가 재로그인해야 하는 불편함이 존재하지만 충분히 감수할 만 하다.

다만 이것이 탈취에 대해 완전한 안전함을 보장하는 것은 아니다.
만약 access token과 refresh token을 갱신하는 시점에 둘 다 탈취당하고, 진짜 유저가 더 이상 서비스를 이용하지 않는다면 DB의 refresh token을 갱신하지 않기 때문에 탈취자가 계속 refresh token을 통해 access token을 발급받을 수 있을 것이다. 애초에 토큰을 사용한 인증 방식은 토큰을 탈취당하지 않도록 대책이 따로 필요하다.

왜 Redis에서 Refresh Token을 관리할까?

Redis를 사용했을 때 장점

  • 인메모리 DB 방식으로 빠르게 접근이 가능하며, Key-Value 구조로 속도가 빠름
  • Refresh token은 영구적으로 저장할 필요가 없으므로 인메모리 DB 방식이 알맞음
  • 캐시처럼 데이터 만료시간을 정할 수 있음
  1. TTL(만료시간)을 Refresh Token의 유효기간과 같게 만들어 효과적으로 관리가 가능하다.
  2. Refresh Token은 호출 빈도가 매우 높다. 따라서 관계형 데이터베이스보다는 인메모리 DB에 저장하는 것이 더 적절하다.

물론 인메모리 DB는 RDB에 비해 안정성이 부족한 것은 사실이다. 하지만 만약 인메모리 DB가 휘발되더라도, 모든 사용자가 다시 로그인을 하면 될 뿐이다. Trade-Off를 생각해 보면, 사용자의 불편이 있더라도 성능적으로 이점을 챙기는 부분이 더 크다고 생각된다.

profile
백엔드를 잘 하고 싶은 사람

0개의 댓글