Refresh Token 사용 이유와 Redis를 활용한 관리 방법: Blacklist, TTL, 보안 강화
728x90

토큰 기반의 인증 방식

  • 토큰 기반 인증(Token-based Authentication)은 사용자 인증 후, 사용자에게 특정한 토큰을 발급하여 이후 요청 시 이 토큰을 통해 인증을 확인하는 방식
  • 대표적으로 JWT(JSON Web Token) 같은 형태의 토큰이 많이 사용된다. 사용자가 로그인에 성공하면 서버는 사용자의 권한과 정보를 포함한 JWT를 발급하여 클라이언트에 전달한다.
  • 클라이언트는 서버와 통신할 때마다 이 토큰을 포함하여 서버에 요청을 보내며, 서버는 토큰을 확인하고 요청을 처리한다.

세션 기반 인증과의 차이

  • 세션 기반 인증에서는 서버에 사용자마다 세션 정보를 저장하고, 클라이언트는 세션 ID를 통해 인증을 유지한다. 클라이언트가 많아질수록 서버에 큰 부담을 줄 수 있다.
  • 토큰 기반 인증은 서버에서 인증 상태를 저장하지 않아도 된다.(stateless) -> 서버는 클라이언트가 보유한 토큰만으로 요청을 검증하므로, 확장성이 좋고, 서버의 부담이 줄어든다.

Refresh Token의 필요성

why? 보안 상의 이유로 Access Token의 유효 기간을 줄이면서 사용자의 불편함이 생겨서

  • Access Token은 비교적 짧은 만료 시간을 갖는다. 이 이유는 보안을 강화하기 위함인데, 만료 시간이 짧을수록 도난 시 피해가 줄어들기 때문이다. ( Access Token이 노출되면 사용자가 아닌 사람이 이를 사용할 수 있음. )
  • 하지만 Access Token이 자주 만료되면 사용자가 로그인을 반복해야 하는 불편함이 생기기 때문에 Refresh Token이 필요하다.

 

Refresh Token의 역할

 

  • Refresh Token은 더 긴 유효 기간을 가지고 있으며, Access Token이 만료되었을 때 새로운 Access Token을 발급받기 위해 사용된다.
  • Refresh Token은 주로 서버 측에서만 관리하여, 사용자나 클라이언트가 이를 보관하지 않도록 한다.
    • 하지만 refresh token을 사용하면 원래의 토큰 기반 방식의 stateless 특징을 좀 벗어나게 된다.
    • Refresh Token을 Redis 등에 저장해 관리하면 서버는 각 클라이언트의 Refresh Token을 보유하게 되며, 이로 인해 약간 stateful한 특성이 추가된다. 서버가 각 사용자의 Refresh Token을 유지해야 하므로, 완전한 stateless 상태는 아니다.

 

Refresh Token을 관리하는 방법

  • Redis 사용 : refresh Token은 빠르고 확장성이 좋은 Redis와 같은 인메모리 데이터베이스에서 관리하면 효율적이다. Redis의 TTL 설정을 통해 만료 기간을 관리하고, 분산 서버 환경에서도 일관된 상태를 유지할 수 있다.
    • RDBMS를 사용할 경우, 토큰의 TTL 관리가 상대적으로 쉽지 않다. 주기적으로 토큰의 만료 여부를 확인하고 삭제해야 하므로 백그라운드 스케줄러가 필요할 수 있다.
    • NoSQL은 확장성 및 유연성이 높아 토큰의 분산 저장이 용이하지만, TTL 관리 기능이 Redis보다 한정적이다.
  • Blacklist 사용: 사용자가 로그아웃하고, 엑세스 토큰이 도난된 경우 블랙리스트에 추가해 악용을 방지할 수 있다. (자세한 내용은 아래를 참고하세요.)

Redis 

  • Key-Value의 형태의 데이터베이스이기 때문에 적은 메모리로도 데이터를 저장할 수 있으며, 작성 속도가 빠름
  • Key-Value 형태를 가지고 있기 때문에 키를 알고 있다면 조회 성능이 O(1)까지 나온다는 장점을 가짐
  • 인메모리 DB 방식으로 빠르게 접근이 가능
    • In-Memory 데이터베이스는 다른 일반 DB들처럼 SSD, HDD와 같은 보조기억장치가 아닌, 프로세서가 직접 액세스할 수 있는 컴퓨터의 주 메모리인 RAM에 데이터를 저장한다.
    • 원래는 HDD or SSD -> Load -> RAM -> Read -> CPU 하는 과정이 있어야 하는데 바로 인메모리 데이터베이스는 바로 RAM에 저장하기 때문에 빠르다.
  • 휘발성인 In-Memory DB는 영구적으로 저장될 필요가 없는 Refresh token을 관리하기에 충분
  • 캐시처럼 데이터 만료일을 정할 있음

도입 이유

  • RDB와는 다르게 토큰의 만료일과 똑같이 맞춰두어 관리하면 토큰이 만료되면 Redis에서도 토큰이 삭제 (TTL 설정)
  • 대체로 15~2시간 단위로 갱신하는 JWT Access Token 새롭게 갱신하기 위해 Refresh Token 필요한데,
    • 호출 빈도가 높은 refresh token은 RDB에 저장하는 것보다 In-Memory DB에 저장하는 것이 훨씬 효율적이다.
  • BUT!! In-Memory DB 휘발성 메모리이기 때문에 전원이 끊어지면 데이터가 전부 지워집니다.
    • Refresh Token만을 관리하기 위해 Redis 사용한다면? -> 단점이 커버될만한 장점을 갖고 있다.
  • Refresh Token 모두 삭제되었을 발생하는 가장 사건은 모든 유저가 재로그인을 해야하는 문제가 발생한다.
    • + 복제 구조를 통해서 바로 복구가 가능하게 해두면 괜찮을 수 있다.

Blacklist 

도입 이유 : Access Token 유효기간과 보안 문제

  • 사용자가 서비스에서 로그아웃할 때 Access Token과 Refresh Token을 삭제하더라도, Access Token의 남아 있는 유효기간 동안 탈취 위험이 존재한다.
    이를 방지하기 위해 로그아웃 시 Access Token을 블랙리스트에 등록하여 남은 유효기간 동안만 이를 사용하지 못하도록 할 수 있다.

Blacklist?

  • 블랙리스트는 로그아웃한 사용자의 Access Token을 별도로 관리하여, 해당 토큰으로의 인증을 차단하는 방식
  • 로그아웃 시 Access Token을 블랙리스트에 추가하여 만료 시간을 설정해주면, 해당 기간 동안 이 토큰이 탈취되어 사용되더라도 서버에서 차단할 수 있다.

로직

  1. 로그아웃 요청
    • 사용자가 로그아웃할 때 Access Token을 서버로 전송
  2. 블랙리스트에 추가
    • 서버는 해당 Access Token을 Redis 블랙리스트에 저장.
    • 이때 남은 유효기간만큼 TTL을 설정하여 Redis에 기록.
      • TTL: 로그아웃 시 Access Token의 남은 유효기간
  3. 유효기간 이후 자동 삭제
    • 유효기간이 지나면 Redis에서 블랙리스트가 자동으로 삭제되어, 시스템에 부하를 주지 않고 토큰을 관리
  4. 블랙리스트 조회
    • 모든 요청마다 Redis 블랙리스트를 조회하여, 해당 Access Token이 블랙리스트에 있으면 요청을 거부.
    • 탈취된 토큰으로 의심될 경우, 보안적으로 위험한 요청을 차단할 수 있음.
728x90
반응형