TIL

[240108] Refresh Token 구현 전의 고려 사항

진진리 2024. 1. 8. 21:05
728x90

토큰 방식을 사용하는 이유

  • 상태를 서버에 저장하지 않으므로 확장성이 좋음
  • 서버 간의 데이터 동기화 문제를 해결하기 쉬움

-> 하지만 백엔드만 구현하는 프로젝트에서는 refresh token을 서버에서 저장함

 

 

RefreshToken을 사용하는 이유

  • 만료기한이 짧은 access token만 사용하는 경우 사용자가 토큰이 만료될 때마다 로그인해야 하는 불편함을 겪게 됨
    • 자동 로그인 구현으로 편의성 증가
  • Access token의 수명을 짧게 하여 accesstoken 노출되더라도 짧은 시간 내에 만료되게 함으로써 보안성을 높일 수 있음

백엔드 프로젝트에서의 Refresh Token 구현

 

Redis를 사용하는 이유

  • 인메모리 DB로 빠른 응답이 가능
  • TTL을 지원하여 토큰의 만료시간을 지정하고 관리하는데 유용함
  • Key-Value 구조로 refresh token을 쉽게 저장하고 검색할 수 있음

 

Access Token과 Refresh Token의 작동 방식 구상

  1. 사용자가 회원가입 후 로그인
  2. 서버에서 access token과 refresh token을 발급
    • access token에 어떤 사용자 정보를 담아야 할까?
      • 사용자 아이디와 닉네임은 사용자가 변경 가능함
      • 사용자 id를 고유한 값으로 해서 사용하자.
    • refresh token에는 만료 기한만 담는다.
    • redis에 refresh token를 key값으로, 사용자 id를 value값으로 하여 저장한다.
      • 이미 존재하는 경우 삭제하고 새로 저장
    • 헤더에 access token, refresh token 값을 담아 전송
  3. 사용자가 만료된 access token으로 접근한 경우
    • 클라이언트 쪽에서 refresh token을 보관하다가 필요할 때 access token과 함께 보낸다는 가정 하에 로직을 구성
      • refresh token 값이 존재하지 않는 경우 refresh token이 유효하지 않다는 예외처리
      • 유효한 refresh token이 존재하는 경우 새로 access token을 발급
      • refresh token이 만료된 경우 재로그인을 요청한다.
  4. 사용자가 로그아웃 하는 경우 -> 블랙 리스트 개념 도입
    • 사용자가 로그아웃시 access token을 담아서 요청
    • access token의 남은 유효기간만큼 Redis에 유효기간을 설정하여 블랙리스트로 등록
      • access token의 유효기간이 끝나면 자연스럽게 Redis에서 삭제시켜 메모리에 남아있지 않도록 함
      • 한 번 로그아웃하면 해당 access token을 다시 사용할 수 없음
        • 결국은 access token의 서버 저장도 어느정도 필요해보임
        • 토큰 방식의 이점을 가져간다고 말할 수 있을지?
    • 로그아웃을 하는 경우 refresh token을 함께 보낸다고 가정하고 refresh token을 redis에서 삭제

프론트엔드까지 구현하는 경우

  • Refresh Token을 서버에 저장할 필요없음
    • access token이 만료된 경우 서버에서 401 응답
    • 해당 응답을 받으면 클라이언트가 refresh token을 함께 담아서 전송
    • refresh token이 만료된 경우 재로그인 요청
    • refresh token이 만료되지 않은 경우 access token 재발급
  • 로그아웃의 경우
    • 사용자가 가지고 있는 토큰을 삭제
    • 만약 사용자가 가지고 있던 토큰을 탈취당한다면?
      • 토큰을 서버에서 제어한다면 토큰 방식의 이점이 사라지는건 아닐까?
      • 그 외 해결 방법: 토큰의 유효기간을 짧게 설정, HTTPS 사용, 민감한 작업의 경우 재인증 요구

Refresh Token을 구현하기 전에 여러가지 것들을 고려해보았다.
처음에는 클라이언트에서 refresh token을 저장한다면 서버에서 redis를 통해 refresh token을 저장 및 관리할 필요가 없는 건 아닐까? 라는 생각을 하게되었다.
그렇지만 refresh token을 저장하는 방식은 토큰이 탈취당하는 경우를 고려했을 때 보안성을 높일 수 있고 로그아웃을 고려해도 모든 토큰을 항상 저장하는 것이 아니기 때문에 어느정도는 토큰 방식의 이점도 가져갈 수 있지 않을까하는 생각이 들었다. 이 부분은 좀 더 생각해볼 필요가 있어 보인다.
일단은 프론트에서 access token만 담아 요청을 보내고 만료됐을 경우 refresh token을 함께 보내준다는 가정하에서 구현을 진행해보려고 한다.