모던 웹 서비스에서의 유저 인증은 대부분 Token 기반 인증을 사용하고 있습니다.
과거 react를 공부하며 token 기반 인증 기능을 개발하는데 많은 시간을 썻던 기억이 있습니다.
다시 블로그를 시작하려고 확인해보는데 "React-axios를 사용하여 토큰 갱신 후 헤더를 변경하는 방법" 의 조회수가 가장 많이 나오고 있었습니다.
해당 글의 내용과 자료를 좀더 보충하기 위해 새로 포스팅을 하고자 합니다.
토큰 기반 인증이 뭔지에 대해서는 타 블로그나 검색을 통해 충분히 알아보실 수 있습니다.
단순히 react와 axios를 사용하여 토큰 기반 인증 기능을 개발하는 것 뿐만 아니라
지루할수도 있지만 한번쯤은 고민해봐야할 내용들도 같이 포함시켰습니다.
토큰 기반 인증 기능을 개발할 때 신경써야할 점
개인적으로 생각하는 토큰 기반 인증을 개발할때 가장 신경써야할 점은 다음과 같습니다.
1. Token에 어떤 정보를 넣을 것인가?
2. Access Token의 만료 시간은 얼마나 되고 어떻게 갱신 시킬 것인가?
3. Refresh Token의 만료 시간은 얼마나 되고, Refresh Token도 갱신 시킬 것인가?
1. Token에 어떤 정보를 넣을 것인가?
서버에 로그인 API 호출하고 성공적으로 로그인이 되었을 때, JWT 토큰을 서버로부터 발급받았습니다.
하지만 일반적으로 토큰은 decode가 됩니다. base64로 인코딩 되어 있기 때문이지요.
물론 토큰의 위조를 방지하기 위하여 signature를 사용합니다. (절대로 유출되면 안되는 키 입니다.)
물론 암호화를 통해 토큰을 안전하게 사용할 수도 있겠지만, 때로는 이것이 좋은 선택이 아닐 수 있습니다.
(시간과 비용, 버그, 레거시 등등의 문제들 때문이지요)
흔히들 사용하는 일반적인 JWT를 보면 아주 쉽게 디코딩 되고 JWT 내에 어떤 데이터들이 들어있는지 확인할 수 있습니다.
jwt.io 에서 쉽게 확인할 수 있습니다.
따라서 토큰 내에 무분별하게 많은 정보가 존재하면 서비스 보안에 취약할 수 있습니다.
(그 외에도, 토큰의 길이가 길어지기 때문에 리소스가 더 많이 들겠죠?)
그럼으로 우리가 일반적으로 JWT 토큰을 사용할 때에는 최소한의 정보만을 사용하는 것이 좋습니다.
2. Access Token의 만료 시간은 얼마나 되고 어떻게 갱신 시킬 것인가?
몇몇 서비스를 보면 토큰 발급 시, Access Token 하나만 발급하는 경우가 있습니다.
이를 디코딩 해보면 토큰의 만료시간이 몇십년 또는 백년이 넘어가는 경우도 존재합니다.
만약 xss와 같은 해킹 공격으로 토큰을 탈취당하게 된다면 해당 토큰의 계정을 몇십년 또는 백년이 넘어가는 아주 긴 시간동안 씹고 뜯고 맛보고 즐길 수 있게 됩니다.
따라서 Access Token과 Refresh Token (인증용 토큰과 갱신용 토큰)을 같이 발급하고 서비스의 환경에 맞게 만료 시간을 적절히 선택해야 합니다.
3. refresh token의 만료 시간은 얼마나 되고, refresh token도 갱신 시킬 것인가?
Refresh Token에도 만료 시간이 존재합니다.
Refresh Token이 만료되면 더 이상 Access Token을 갱신하지 못하게됩니다.
따라서 Refresh Token도 갱신시켜주어야 지속적으로 Access Token을 갱신할 수 있습니다.
타 서비스를 살펴보면 Access Token 갱신 시, Refresh Token을 같이 갱신시켜주거나
Refresh Token의 만료 시간을 확인하여 만료 몇 일전에 Access Token 갱신 요청 시 Refresh Token을 같이 갱신시켜주기도 합니다.
이 모든 선택은 개발하는 서비스의 유형에 맞게, 그리고 관련 협업자들과의 논의를 통해 결정해야 합니다.
Token 정책
본 글에서는 React와 Axios를 사용한 웹 어플리케이션을 대상으로, 설명 및 테스트가 목적임으로 간략한 토큰 정책을 가지고 진행할 예정입니다.
1. Access Token 의 만료 시간은 5분
2. Refresh Token 의 만료 시간은 10분
3. Access Token 갱신 요청 시, Refresh Token도 같이 갱신
4. Token 에는 User의 Primary Key 정보를 포함
개발에 앞서서
1. 개발하기에 앞서, 토큰을 어디에다 저장할 것인가?
우리가 웹 플랫폼 (브라우저) 에서 이런 정보를 저장할 수 있는 곳은 크게 3가지가 있습니다.
1. 세션 스토리지
2. 로컬 스토리지
3. 쿠키
(세션/로컬 스토리지는 웹 스토리지라고 하며 2가지로 구분할 수도 있습니다.)
3가지 모두 장단점이 존재합니다. (시간, 리소스, 보안 등)
따라서 상황에 맞게 적절하게 선택하면 됩니다.
본 글에서는 로컬 스토리지에 토큰을 저장할 것입니다.
2. Token Refresh 과정
토큰을 갱신하는 과정을 살펴보겠습니다.
1. POST /api/v1/auth/login 로그인 요청
2. 로그인 성공 시, 서버로부터 Access, Refresh Token을 Response로 전달 받고 해당 토큰을 로컬 스토리지에 저장
3. 인증이 필요한 API 요청 시, header에 Access Token을 포함하여 요청
4. 만약 http status code 401 (unauthorized) 가 반환되면 이전 요청을 가지고 있고,
5. refresh 토큰을 이용하여 POST /api/v1/auth/token/refresh 요청 후
5. 성공적으로 Token이 갱신되면 갱신된 Access, Refresh Token을 Response로 전달 받고 로컬 스토리지 내의 토큰과 교체
5-1. 실패하면 로그아웃 처리
6. 이전 요청의 헤더의 토큰을 갱신된 토큰으로 변경한 후, 재전송
3. Axios Interceptor
axios 에는 interceptor 라는 좋은 친구가 있습니다.
Request나 Response를 보내고 받기 전 (then, catch 처리 전) 가로채는 기능입니다.
interceptor를 사용하여 인증이 필요한 요청을 보낼 때 localStorage에 있는 Access Token을 가져와 헤더에 넣고
401 status code Response가 왔을 때, 토큰 갱신 후, 다시 재전송할 수 있습니다.
다음 글에서 본격적으로 코드를 다뤄보겠습니다.
'Develop > React' 카테고리의 다른 글
react, axios를 사용한 token 인증 기능 개발 (2) (0) | 2022.09.04 |
---|---|
React-axios를 사용하여 토큰 갱신 후 헤더를 변경하는 방법 (2) | 2021.08.13 |