Access Token의 문제점

사용자의 잦은 로그아웃 경험

현재 진행중인 나몰닭 프로젝트는 Access Token 만을 사용하여 사용자를 인증한다. Access Token 유효 기한인 1시간이 지나면 유저는 로그아웃되고 다시 로그인을 진행해야 한다. 게임을 하다 중간에 방을 나왔을 때 로그인을 다시해야 한다면 굉장히 불편한 서비스 경험이 될 것이다. 그렇다고 유효 기간을 길게 한다면 아래와 같은 보안상의 문제가 발생한다.

 

보안 문제

Access Token은 JWT이므로 그 자체로 인증 정보를 모두 가지고 있어서 탈취되면 위험한 상황이 발생할 수 있다.  토큰 기반 인증 방식에서 토큰은 세션과 다르게 stateless 하다. 서버가 상태를 보관하고 있지 않다는 이야기이다. 서버는 한번 발급한 토큰에 대해서 제어권을 가지고 있지 않다. 즉, 토큰이 탈취될 경우 서버에서 토큰이 만료될때까지 기다리는 것 말고는 막을 방법 없이 사용자 계정의 제어권을 해커에게 내어줄 수 밖에 없다는 것이다. 

 

Refresh Token 이란?

목적

Refresh Token의 목적은 Access Token의 유효 기간을 짧고, 자주 재발급 하도록 만들어 보안을 강화하면서도 사용자에게 잦은 로그아웃 경험을 주지 않도록 하는 것이다.

Access Token은 리소스에 접근하기 위해서 사용되는 토큰이라면, Refresh Token은 기존에 클라이언트가 가지고 있던 Access Token이 만료되었을 때 Access Token을 새로 발급받기 위해 사용한다.

Refresh Token은 서버에 저장되기 때문에(stateful) refresh token이 해커에 의해 탈취당했다고 판단되었을 때 서버에서 refresh token을 삭제함으로써 강제 로그아웃을 시킬 수 있다. 이런 특징을 이용해서 access token + refresh token의 조합을 구성하면 access token의 경제적인 장점 refresh token의 보안적인 장점을 둘 다 챙길 수 있다.

 

유효 기간

Refresh Token은 Access Token 대비 긴 유효 기간을 갖는다. Refresh Token을 사용하는 상황에서는 일반적으로 보안적으로 취약한  Access Token의 유효기간은 30분 이내, Refresh Token의 유효기간은 처리 비용이 많이 들기 때문에 2주 정도로 설정한다고 한다. 유효 기간은 서비스 성격에 따라 적절하게 설정 해야한다.

 

Access Token + Refresh Token 인증 과정

https://tansfil.tistory.com/59

 

1. 사용자가 ID , PW를 통해 로그인한다.

2. 서버에서는 회원 DB에서 값을 비교한다. 

3~4. 로그인이 완료되면 Access Token, Refresh Token을 발급한다. 이때 일반적으로 회원DB에 Refresh Token을 저장한다.

5. 사용자는 Refresh Token은 안전한 저장소에 저장 후, Access Token을 헤더에 실어 요청을 보낸다.

6~7. Access Token을 검증하여 이에 맞는 데이터를 보낸다.

8. 시간이 지나 Access Token이 만료된다.

9. 사용자는 이전과 동일하게 Access Token을 헤더에 실어 요청을 보낸다.

10~11. 서버는 Access Token이 만료됨을 확인하고 권한없음을 신호로 보낸다.

 

** Access Token 만료가 될 때마다 계속 과정 9~11을 거칠 필요는 없습니다.

 사용자(프론트엔드)에서 Access Token의 Payload를 통해 유효기간을 알 수 있습니다. 따라서 프론트엔드 단에서 API 요청 전에 토큰이 만료됐다면 바로 재발급 요청을 할 수도 있습니다.

 

12. 사용자는 Refresh Token과 Access Token을 함께 서버로 보낸다.

13. 서버는 받은 Access Token이 조작되지 않았는지 확인한후, Refresh Token과 사용자의 DB에 저장되어 있던 Refresh Token을 비교한다. Token이 동일하고 유효기간도 지나지 않았다면 새로운 Access Token을 발급해준다.

14. 서버는 새로운 Access Token을 헤더에 실어 다시 API 요청을 진행한다. 

 

Refresh Token의 한계

Access Token을 즉시 차단할 방법의 부재

아무리 Refresh Token이 Access Token의 유효기간을 짧게 만들어 줄 수 있다고 하더라도, 탈취된 Access Token이 유효한 그 짧은 시간 동안에 악용될 수 있다는 위험성이 존재한다.

 

Refresh Token 그 자체를 탈취 당할 가능성

해커에게 Refresh Token 자체를 탈취 당하면 해커는 마음껏 Access Token을 발행할 수 있다. 서버 DB에서 Refresh Token을 저장해 직접 추적하는 방법을 사용하면 조금이나마 피해를 줄일 수 있겠지만, 피해가 확인되기 전까진 탈취 여부를 알 방법이 없다.

RTR을 사용한다면 Refresh Token을 1회 사용하고 버리게 되어 더 안전하게 사용할 수 있지만, 사용하지 않은 Refresh Token을 탈취당하면 해커는 1회 한정으로 Access Token을 발급받을 수 있다.

즉, 이러나 저러나 Refresh Token을 탈취 당할 위험성이 존재한다. 따라서 클라이언트는 XSS, CSRF 공격으로부터 Refresh Token이 탈취되지 않도록 안전하게 보관해야한다.

 

더보기

Refresh Token을 서버에 저장할 시 고려해볼 사항

보안 - 정상적인 사용자의 ip가 아니라면 refresh token을 삭제하도록 하기

refresh token은 서버에 저장된다. 그래서 보안적인 문제가 생기면 refresh token을 삭제함으로써 특정 사용자를 강제 로그아웃시킬 수 있다. 최초 로그인 한 ip를 서버에 저장하고, refresh token을 통한 access token 갱신 요청이 다른 ip로부터 온다면 비정상적인 접근으로 판단하고 refresh token을 삭제하여 강제 로그아웃시킨다.

그런데 이 방식도 UX적으로 단점이 있다. 요즘 항상 같은 곳에서만 컴퓨터를 사용하는 유저가 얼마나 되겠는가. 지금 글을 작성하는 시점에도 많은 사람이 카페에서 노트북을 사용하고 있는데 ip가 달라진다고 해서 강제로 로그아웃시킨다면 사용자 경험에 좋지 않을 것이다.

-->  네이버나 카카오톡처럼 ip가 달라지는 경우 보안 알림을 사용자에게 띄워 준다. 여기서 “아니요” 를 선택한다면 로그아웃되는 구조로 풀 수 있을 것 같다.

 

UX - 사용 중에 access token이 만료된다면 조용히 재발급 받기

만약 어떤 사용자가 새로 고침하지 않고 화면을 2시간 이상 띄워놓는 경우를 가정해보자. 가장 흔한 경우는 글을 작성하는 경우가 있다. 이 경우에는 access token이 만료되었다는 사실을 사용자가 모르게 하는 것이 가장 자연스러운 경험일 것이다.

 

방법 1) 요청 보낼 때 token 만료 에러가 발생하면 token을 새로 발급받기

인가가 필요한 요청을 보낼 때 token 만료 에러가 발생하면 token을 새로 발급받고, 새로 발급받은 token으로 다시 요청을 다시 보내는 것이다.

장점

  • 사용자가 인가가 필요한 작업을 요청할 때만 token이 재발급되어 경제적이다.

단점

  • 인가가 필요한 요청에 대한 에러처리, 재요청 로직이 추가로 요구된다.
  • token이 만료된 경우 인가가 필요한 요청을 결과적으로 2번 보내야한다.
  • token이 만료된다면 첫번째 요청은 실패할 것이고, 새로운 token을 발급받아 두번째 요청을 보내야 한다. 큰 문제가 되지는 않을테지만 단점이라 할 수 있다.

방법 2) 일정 시간마다 새로운 access token을 발급 받기

access token 만료 기간이 2시간이라면 1시간 55분 정도에 새로운 token을 발급한다. 이 방법을 사용하면 요청 관련 로직을 수정하지 않아도 되어 편리하다. 사용자가 사용하지 않을 때에도 백그라운드에서 계속 새로운 token을 발급받는다는 단점이 있을 수 있지만, 이것도 브라우저 포커스가 되어있는지를 감지해서 최적화도 가능하므로 큰 문제가 되지 않을 것으로 생각한다.

장점

  • setTimeout으로 token 재발급 로직만 작성해주면 요청 관련 로직 수정이 필요 없다.

단점

  • 시간과 관련하여 token을 재발급 받기 때문에 특정 시간이 지나면 무조건 재발급 요청을 보내어 비효율적일 수 있다.

 

 


[ 참고 자료]

 

 

refresh token 도입기

❗ SSR 상에서 refresh token을 도입하면서 느낀 것들을 작성한 글입니다. ❗ SSR에서 로그인이 어떻게 이루어지는지 궁금하시면 여기를 참고해주세요! 도입 계기 - 2시간이 지나면 로그인이 풀린다!

tecoble.techcourse.co.kr

 

Spring Boot와 Redis를 사용하여 Refresh Token 구현하기

배경 바로 직전에 작성한 Access Token의 문제점과 Refresh Token 글에서 Refresh Token이 무엇인지 글로 알아보았다. 하지만, 글만 읽어서는 공부를 끝냈다고 할 수 없다. 실제로 코드를 작성해야 지식을

hudi.blog

 

+ Recent posts