Back-end

Refresh token 이란? : Refresh Token을 이용한 자동 로그인 DB 설계하기

hsloth 2024. 8. 22. 23:47
  • 일단, Refresh token은 자동로그인 기능을 구현하기 위한 토큰이다.

Refresh Token을 사용하는 이유


만약, 자동로그인을 구현하는 데 Access Token만 사용한다고 가정해보자.

  • 먼저 Access Token의 유효 기간을 1일로 설정해두고 사용한다면, 사용자는 1일마다 직접 로그인을 해주어야 해서 자동 로그인이 되지 않는다.
  • 이 상태에서 자동 로그인 구현을 위해 Access Token의 유효 기간을 1000일로 늘린다고 하면, 해당 액세스 토큰을 탈취당하면 1000일 동안 공격자가 사용할 수 있기 때문에 보안상 좋지 않다.
  • “아! 그러면 보안을 위해서 Access Token의 유효 기간을 줄이고, Refresh Token을 만들어서 갱신하게끔 해야겠다! 이러면 Access Token이 탈취 당해도 잠깐밖에 사용하지 못하잖아! 그리고 어차피 권한 관련 요청을 할 때는 Access Token만 주고받으면 되니 Refresh Token을 탈취 당할 걱정은 어느 정도 덜 수 있겠다!”
  • 즉, Refresh Token의 용도는 자동 로그인을 구현하기 위해 Access Token의 기간을 늘리는 것보다 Refresh Token(기간을 늘린 Access Token 보다 기간을 짧게)을 두어, 그나마 Access Token 탈취 위험으로부터 안심할 수 있도록 하기 위함이다.

어? 그러면 Access Token을 Refresh Token 처럼 사용해도 되는 거 아닌가요? 스스로 재발급될 수 있도록?

  • 만약 Access Token의 유효 기간을 1시간 정도로 짧게 잡고, Access Token이 만료되면 재발급되도록 로직을 구현해도, Access Token 만 있으면 무한정으로 권한을 가질 수 있기 때문에 이 또한 좋지 않다.
  • 그리고 Access Token 하나가 너무 많은 권한을 가지게 된다. API 접근 권한토큰 재발급 권한을 동시에 가지는 셈
  • Refresh Token은 이 권한을 분리하기 위한 것이다. Access Token은 짧은 유효 기간을 가짐으로서 API 접근 권한을 짧은 시간동안만 가질 수 있도록 하고, Refresh Token은 그런 토큰을 재발급하는 용도로서 권한과 책임을 분리한다.
  • 물론, Access Token과 Refresh Token을 둘 다 탈취당하면 소용이 없지만, 비교적 안전하다는 거지 완벽하다는 것은 아니다. 이 세상에 완벽한 것은 없다.

예상되는 문제점


  • 중복 로그인 문제 (여러 기기에서의 로그인)
  • 기기에 따른 로그인 관리 문제
  • 토큰 탈취 문제

Refresh Token 사용 방법


간단하게 사용하는 방법

  • 간단하다. 유저 테이블에 refresh token 칼럼을 하나 추가해두면 된다. (oauth 테이블은 무시해도 된다)

Access Token 갱신

  1. 사용자가 로그인을 한다.
  2. 서버에서 Access Token과 Refresh Token을 발급하여 클라이언트로 보낸다. 이 때, 유저 DB를 조회하여 이미 발급된 Refresh Token이 있으면 발급되어 있던 Refresh Token을 보낸다.
  3. Refresh Token을 새로 발급했다면, 서버는 발급한 Refresh Token을 DB에 저장한다.
  4. 유저가 Access Token 갱신을 위해 서버 측에 Access Token과 Refresh Token을 전송한다.
  5. 서버는 만료된 Access Token에서 userId를 꺼내고, DB에서 해당 유저를 조회하여 서버가 받은 Refresh Token이 DB에 저장되어 있는 Refresh Token과 일치하는지 확인한다. (이 과정에서 Refresh Token도 JWT로 생성하여 여러 장치를 만들 수 있다. Refresh Token에도 userId를 심어서, Access Token과 Refresh Token의 userId를 비교해서 같으면 갱신이 된다고 하던지… 등) → Access Token의 userId를 확인하는 절차를 거침으로 인해 Refresh Token만으로 Access Token을 발급하는 것을 방지할 수 있다.
    • 만약 위 과정에서 Refresh Token이 Expire되었을 경우, 에러를 뱉는다. 이 경우에는 프론트에서 백으로 Refresh 갱신 요청을 보내야 한다.
  6. 서버가 받은 Refresh Token과 DB의 Refresh Token이 일치한다면, Access Token을 재발급하여 사용자에게 넘겨준다. 불일치한다면, 에러를 뱉고 재로그인을 시키도록 한다.

Refresh Token 갱신

  1. 사용자가 Refresh Token 갱신 요청과 함께 Access Token과 Refresh Token을 서버로 전송한다.
  2. 서버는 사용자의 Access Token과 Refresh Token을 받고, Access Token에서 userId를 추출하여 DB에서 해당유저를 조회하여 서버가 받은 Refresh Token이 DB에 저장되어 있는 Refresh Token과 일치하는지 확인한다. (Access Token과 Refresh Token이 함께 존재해야 Refresh Token 재발급 가능)
  3. 서버가 받은 Refresh Token과 DB의 Refresh Token이 일치한다면 Refresh Token을 재발급한다. 만약 불일치한다면, 에러를 뱉고 재로그인을 시키도록 한다.

예상되는 문제점에 대한 해결

  • 중복 로그인은 해결 가능하다. DB에 저장된 Refresh Token을 이용해서 기기마다 Access Token을 발급해주면 되기 때문
  • 기기에 따른 로그인 관리는 불가능하다. DB의 Refresh Token을 Null로 만들어서 Access Token이 만료되면 자동 로그인 되지 않도록 할 수 있다.
  • 토큰 탈취 문제 또한… 기본적으로 DB의 Refresh Token을 Null로 만들어서 자동 로그인이 되지 않도록 할 수 있으나, Access Token의 경우는 블랙 리스트 테이블을 따로 만들거나 하는 등의 조치가 필요할 듯 하다. (혹은 Redis에서 Access Token의 expire 시간만큼 ttl을 설정해서 사용하면 좋을 듯하다)

문제점

  1. A 기기에서 로그인을 하여 Refresh Token을 발급받은 후 유효 기간이 지난 상태일 때, A 기기에서는 Refresh Token의 유효 기간이 지난 상태 도중 로그인을 하지 않아 Refresh Token 갱신이 이루어지지 않은 상태에서, B 기기에서 로그인을 하여 새로 Refresh Token을 발급받게 될 경우, 유저 테이블의 Refresh Token 값이 바뀌게 되어서 기존에 A 기기에서 사용하던 Refresh Token은 무용지물이 되어 A 기기에서는 무조건 재로그인을 해야한다.
    • 기본적으로 Refresh Token의 기간이 상당히 길기 때문에 일정 기간마다 재로그인 시켜도 크게 문제가 되지는 않는다.
  2. A 기기에서 로그인을 하여 Refresh Token을 발급받은 후 유효 기간이 거의 다 된 상태일 때, B 기기에서 로그인을 하여 기존 Refresh Token을 발급받는다면, 해당 Refresh Token의 유효기간이 매우 짧기 때문에, Refresh Token이 만료가 되고 그 사이에 A 기기에서 Refresh Token을 갱신한다면, B 기기는 자동 로그인이 끊겨 로그인을 한 번 더 해줘야한다.
    • 이 역시 재로그인을 하면 자동로그인 기간이 길게 유지가 되기 때문에 큰 문제가 되지는 않는다.

빡세게 사용하는 방법

마찬가지로 oauth 테이블은 무시해도 된다.

위 문제점을 해결하고 싶다면, 기기마다 Refresh Token을 관리하는 테이블을 두면 된다. 해당 테이블에서 IP, DeviceId, Access Token, Refresh Token, 최근 접속 지역 등을 관리해서 기기마다 로그인 세션을 관리할 수 있다.

  • 이렇게 한다면 기기마다 Access Token, Refresh Token을 관리하기 때문에 첫 번째, 두 번째 문제를 모두 해결할 수 있다.
  • 자동 로그인 기기 대수를 조정할 수도 있고
  • 원하는 기기의 Access Token을 fire하여 사용자가 원하는 디바이스의 로그인 세션을 끊도록 만들수도 있다.

예상되는 문제에 대한 해결

  • 중복 로그인 문제 - 완벽하게 해결 가능. 기기마다 토큰을 따로 관리해서 관리 가능하다.
  • 기기에 따른 로그인 관리 문제 - 완벽하게 해결 가능. 원하면 로그인 세션까지 날릴 수 있고, 기기의 접속 환경 등을 스냅샷으로 관리하여 보다 많은 데이터를 뽑을 수도 있다.
  • 토큰 탈취 문제 - 기기마다 토큰을 관리하기 때문에 토큰 탈취 사실을 알았을 때, 해당 토큰을 무효화 시킬 수 있다. (기기 자체를 벤 먹일 수도 있다)