티스토리 뷰
프로젝트에서 로그인 부분을 맡게 됐다. 이메일 로그인 인증 API 연동까지 완료했고 이메일 인증 코드 검증하는 부분을 하려고 한다. 두 달 전쯤 프로젝트 기획안을 짜면서 로그인 구현을 하게 될 것 같아 accessToken과 refreshToken의 개념에 대해 공부하며 정리했었는데 오늘은 accessToken과 refreshToken을 담는 저장소들의 차이점들을 정리하며 나은 방향을 고민해보려고 한다.
로컬 스토리지, 세션 스토리지
우선 로컬 스토리지, 세션 스토리지 둘 을 합쳐서 웹 스토리지라한다.
HTML5에 추가된 저장소이며 키-값을 저장할 수 있다. (key-value 스토리지 형태라고 한다.)
로컬 스토리지, 세션 스토리지 차이점
둘의 차이점은 데이터의 영구성이다.
로컬 스토리지의 데이터는 사용자가 지우지 않는 이상 계속 브라우저에 남아있는 반면 세션 스토리지의 데이터는 윈도우나 브라우저 탭을 닫을 경우 제거된다.
따라서 자동 로그인 등 지속적으로 필요한 데이터는 로컬 스토리지에, 일회성 로그인 정보 등 일시적으로 필요한 데이터는 세션 스토리지에 저장하면 된다. 여기서 가장 중요한 점은 비밀번호와 같이 중요한 정보는 탈취 될 위험이 있기 때문에 절대 저장하면 안된다.
쿠키(HTTP Only)
그렇다면 로컬 스토리지와 세션 스토리지가 나오기 이전의 저장소 역할을 했던 것은 무엇일까?
바로 쿠키이다.
쿠키는 만료 기한이 있는 키-값 저장소이며 서버에서 쿠키의 httpOnly 옵션을 설정하면 JS에서 쿠키에 접근 자체가 불가능 하기 때문에 XSS(사이트 간 악성 js 코드를 심는 행위)로부터 안전하다. 하지만 CSRF(사이트 간 요청 위조) 공격에는 취약하다는 단점이 있다.
어디에 accessToken과 refreshToken을 담아야 하나?
앞서 쿠키는 XSS 공격에 안전하지만 CSRF공격에는 위험하다고 했는데, 로컬 스토리지와 세션 스토리지는 반대로 XXS 공격에 취약하고 CSRF 공격에 안전하다.
XSS 공격을 통해서는 토큰 값 자체를 가져올 수 있지만 CSRF 공격을 통해서는 로그인 된 상태로 특정 위험한 동작을 하게 만든다고 생각하면 된다. 따라서 쿠키의 경우 CSRF 공격으로 쿠키에 저장되어 있는 토큰 값 자체를 가져오는 것은 아니다. (물론 설계와 공격 형태에 따라 가능성을 아예 배제할 수는 없다.)
따라서 refreshToken은 Access Token을 재발급 받는 요청 외에 인증 인가가 필요한 작업들에 Refresh Token으로는 접근할 수 없기 때문에 쿠키에 저장하도록 하고 AccessToken은 자바스크립트 private 변수로 저장하여 XSS, CSRF 두 가지의 공격을 당할 가능성을 없애기로 했다.
또한 리액트는 SPA이므로 private 변수가 그대로 유지되기 때문에 페이지를 이동할 때 마다 토큰이 날아갈 걱정이 없다. 물론 새로고침을 하면 변수가 날아가겠지만 이 경우에는 추가로 refreshToken만 가지고 accessToken을 발급받는 API를 만들어 주어야 한다.
참고
https://www.zerocho.com/category/HTML&DOM/post/5918515b1ed39f00182d3048
'Tips > 보안' 카테고리의 다른 글
[보안] OAuth 2.0 개념 및 동작 원리 (0) | 2023.08.16 |
---|
- Total
- Today
- Yesterday
- 스프린트프론트엔드6기
- javascript
- 리액트
- 중급 프로젝트
- CSS
- js
- rest parameter
- currentTarget
- react
- 취업까지달린다
- arguments
- 비제어 컴포넌트
- 프론트엔드
- 제어 컴포넌트
- html
- 코드잇스프린트
- tanstackquery
- 유사배열객체
- 코드잇 스프린트
- Git
- GitHub
- Next.js
- hydrationboundary
- 비동기
- map
- Target
- innerhtml
- 동기
- 객체
- 배열
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |