JWT - refresh,access 토큰 정리

2023.01.23

jwt logo

이전까지 jwt에 refresh 토큰과 access 토큰에 대한 간략한 개념만 알고있었고 실제로 써본적이 없었다.
그리고 리프레시와 엑세스 토큰이란걸 처음 알았을 때에는 (대략 2020년 쯤) 구글에 검색을해도 "그냥 이런 방법이 있다" 정도로 소개하는 내용만 있었고 구현 까지는 아니더라도 대략적인 원리와 이유를 설명하는 내용은 거의 없었던걸로 기억한다. 그래서 나도 "아 이런게 있네?" 정도로만 생각했고 포스트 마다 설명이 제각각 이라서 헷갈리는것도 많았다. 최근 사내 프로젝트에서 로그인 기능을 개선해야할 일이 생겼는데 이 참에 리프레시,엑세스 토큰 개념도 정리를 해보기로 했다.


이 포스트에는 여러가지 경우의 수와 구현에 관한 내용은 전부생략했다. refresh-access 토큰 관련 포스트를 여럿 읽어봤지만 설명하는 내용이 전부 다르다. 그리고 구현에 관한 내용도 사실은 정답이 없기에 본인이 필요한 방식대로 구현하면 된다. access 토큰과 refresh 토큰의 기본개념을 알고 있다면 내가 고민하고 헷갈렸던 아래의 의문점들 부분을 읽어보자.

refresh랑 access 토큰

access token 이란 실제 api의 서비스에 접근할수있는 권한을 가진 토큰이다. 하지만 이 토큰을 가지고 있다면 누구나 api 서비스를 사용할수가 있다 그니까 해킹에 매우 취약하다는건데 이 문제를 해결하기 위한 방법중 하나가 토큰의 유효기간을 매우 짧게 설정하는것이다. 만약 토큰의 유효기간이 10분이라면 해킹을 당해도 10분동안만 유효하기때문에 피해를 줄일수가 있다. 하지만 정말 유효기간이 10분이라면 사용자는 매번 10분마다 로그인을 해야한다.
그래서 이런 귀찮음을 방지하기 위해 refresh token이라는 걸 하나더 만든다. refresh 토큰은 access 토큰을 발급받기 위한 토큰인데 유효기간을 길게 설정하여 refresh 토큰이 유효한 동안은 로그인없이 자동으로 access 토큰을 갱신하도록 하는 방법이다. 대략적인 사용 방법은 아래와 같다.


  1. 로그인을할때 refresh와 access 토큰 두개를 생성하고 사용자는 이 두개의 토큰을 가지고 있는다. (중요) 이때 refresh 토큰은 서버에서 저장한다.
  2. api 요청을 할때는 엑세스 토큰을 보낸다. (이 부분에 대해서도 refresh와 access를 둘다 보낸다 또는 access 토큰만 보낸다 로 의견이 갈린다.)
  3. 만약 access 토큰이 만료가 되었다 -> refresh 토큰을 검사후 유효하다면 새로운 access 토큰을 발급한다. (이때 사용자가 보낸 토큰과 서버에서 가지고 있는 refresh 토큰과 비교를 한다)
  4. 만약 refresh 토큰도 만료가 되었다면 권한없음 오류를 내보내고 클라이언트에서는 로그인 페이지로 이동시킬수 있다.

#의문점들


questions


아 refresh 쓰는 이유랑 방법은 알겠는데 대체 원리가 뭐임?

여러개의 포스트를 읽었지만 어디에도 원리와 이유를 설명하는 포스트는 없었고 잘못된 내용을 전달하는 포스트도 있었다. 그리고 내가 느꼈던 의문들을 아래에 정리해봤다.


refresh 토큰이 탈취되면 소용 없는거 아님?


애초에 리프레시 토큰을 쓴다는거 자체가 만약에 엑세스 토큰이 해킹당했을때 대비하기 위해서 쓰는건데 리프레시 토큰이 탈취되면 소용없는거 아님?


정답이다.
리프레시 토큰은 엑세스 토큰을 발급받기 위해 존재하고 이게 해킹당했다면 당연 엑세스 토큰도 발급받을수있다. 하지만 refresh 토큰은 무효화를 할수 있다는 점이다. 위에서 설명했듯이 refresh 토큰은 서버에서도 저장을 하고있다. 상황에 따라 이 refresh 토큰자체를 무효화 시켜버리면 더이상 access 토큰을 발급할수 없게 할수도 있다.

예를 들어보자,
사용자 A가 유효기간이 2주인 refresh 토큰을 해킹당했다. 만약 아무 조치를 취하지 않는다면 2주동안 해커는 자유롭게 A의 계정을 사용할수있다. 이때 A는 로그아웃을 하든 아니면 관리자에게 문의를 하든 해서 현재 서버에 저장된 refresh 토큰을 삭제시켜버린다. 그리고 해커가 해킹한 refresh 토큰으로 access 토큰을 받으려고 하지만 서버에는 A에 대한 refresh 토큰을 가지고 있지 않으므로 해당 refresh 토큰을 무효하다고 판단하고 요청을 거부할수가 있다.


refresh 토큰을 서버에서 저장하면 stateful 이 되는거 아님?


애초에 jwt 라는걸 쓴다는거 자체가 stateless한 로그인 때문에 쓰는건데 이렇게 토큰을 서버에서 저장을 한다는거 자체가 jwt의 장점을 버리는거 아님?


이 부분에 대해서는 아직 해답을 찾기 못했다. 이게 정말 stateful 로써 jwt의 장점을 버리는 방법인지도 아닌지도, 서버에 refresh 토큰을 저장하지 않는 다른 방법을 찾지도 못했다. 한가지 깨달은것은 jwt든 세션 로그인이든 각각의 장단점이 있고 절대 완벽한 방법은 없다 라는것이었다.
그리고 세션 로그인 방식과의 차이점이라면 refresh 토큰은 DB에 저장을 한다는점이고 세션로그인은 메모리에 저장을 한다는 점이다.


Do you want something exciting?

© 2022. YSH All rights reserved.