728x90
반응형
학습 주제
- ch. 23 - 24 JWT를 통한 회원 인증 시스템 구현하기
💡 JWT의 이해
- JSON Web Token의 약자로, 데이터가 JSON으로 이루어져 있는 토큰을 의미한다.
- 쉽게 말해, 모바일이나 웹의 사용자 인증을 위해 사용하는 암호화된 토큰이다.
- 두 개체가 서로 안전하게 정보를 주고받을 수 있도록 웹 표준으로 정의된 기술이다.
- 사용자의 정보 열람, 수정 등 개인적인 작업들을 수행할 수 있다.
세션 기반 인증 시스템
- 서버가 사용자가 로그인 중임을 기억하고 있는 것.
- 사용자가 로그인하면 서버는 세션 저장소에 사용자 정보를 조회하고 세션 id를 발급한다. 발급된 id는 브라우저의 쿠키에 저장한다. 이후에 사용자가 다른 요청을 보낼 때마다 서버는 세션 저장소에서 세션을 조회한 후 로그인 여부를 결정하여 작업을 처리하고 응답을 한다.
- 단점
- 서버를 확장하기가 번거롭다. 서버의 인스턴스가 여러 개가 되면, 모든 서버끼리 같은 세션을 공유해야 하므로 세션 전용 데이터베이스를 만들어야 한다.
토큰 기반 인증 시스템
- 토큰은 로그인 후 서버가 만들어 주는 문자열. 해당 문자열 안에 사용자 로그인 정보가 들어 있고, 해당 정보가 서버에서 발급되었음을 증명하는 서명이 있다.
- 사용자가 로그인을 하면 서버에서 사용자에게 해당 사용자의 정보를 지니고 있는 토큰을 발급해 주고, 추후에 사용자가 다른 API를 요청할때 발급받은 토큰과 함께 요청한다. 그러면 서버는 해당 토큰이 유효한지 검증한 후 결과에 따라 작업을 처리하고 응답을 한다.
- 장점
- 서버에서 사용자 로그인 정보를 기억하기 위해 사용하는 리소스가 적다.
- 사용자 쪽에서 로그인 상태를 지닌 토큰을 가지고 있어 서버의 확장성이 높다. 서버의 인스턴스가 여러개로 늘어나도 서버끼리 사용자의 로그인 상태를 공유할 필요가 없음.
- 보통 토큰 발급만 해주는 인증서버가 따로 존재한다.
토큰 발급
- 사용자가 브라우저에서 토큰을 사용할 때 두 가지 방법이 있다.
- 브라우저의 localStorage 혹은 sessionStorage에 담아서 사용하는 방법
- localStorage
- 저장한 데이터를 명시적으로 지우지 않는 이상 영구적으로 보관이 가능하다.
- 도메인마다 별도로 localStorage 가 생성되고, 도메인만 같으면 전역적으로 공유 가능하다.
- 브라우저를 종료해도 데이터는 보관되어 다음번 접속에도 그 데이터를 사용할 수 있다.
- sessionStorage
- 데이터가 지속적으로 보관되지 않는다. 현재 페이지가 브라우징되고 있는 브라우저 컨텍스트 내에서만 데이터가 유지된다.
- 브라우저가 종료되면 데이터도 같이 지워진다.
- 도메인별로 별도로 생성된다. 같은 사이트의 같은 도메인이라 할지라도 브라우저가 다르면 서로 다른 영역이 된다.
- 하지만, Web Storage에 담아 사용하는 방법은 페이지에 악성스크립트를 삽입하여 토큰 탈취할 수 있는 XSS공격에 취약하다.
- XSS(Cross Site Scripting) 공격
- 악의적인 js 코드를 웹 브라우저에 삽입하여 실행시키는 공격이다. 이 방법으로 브라우저에 저장된 토큰과 같은 중요 정보들을 탈취할 수 있다.
- XSS 공격을 막는 것은 웹 보안을 위한 최소한의 조치이다.
- 아무리 다른 공격 (CSRF 등)에 대한 조치를 해도, XSS가 뚫린다면 아무 소용이 없다.
- JS 코드로 의도하지 않은 request를 날리거나 Local Storage, 변수 값 등 모든 것이 탈취 가능하기 때문이다.
- XSS(Cross Site Scripting) 공격
- localStorage
- 브라우저의 쿠키에 담아서 사용하는 방법
- httpOnly 속성을 활성화하여 자바스크립트를 통해 쿠키를 조회할 수 없으므로 악성 스크립트로부터 안전하다.
- 대신, 토큰을 쿠키에 담으면 사용자가 서버 요청할 때마다 무조건 토큰이 함께 전달되는 점을 이용하여 사용자 모르게 원치 않는 api 요청을 하게 만드는 CSRF 공격에 취약하다.
- CSRF(Cross Site Request Forgery) 공격
- request를 가로채 사용자인 척 하고 백엔드 서버에 변조된 request를 보내 악의적인 동작을 수행하는 공격이다. (사용자 정보 수정 및 정보 열람)
- XSS를 막으면 CSRF도 막을 수 있는가?
- 아니다. 사용자 브라우저의 js를 조작하여 공격하는 XSS와 성격이 다르다. 이미지 태그나 링크로도 사용자 브라우저에서 악의적인 request를 보낼 수 있다.
- CSRF(Cross Site Request Forgery) 공격
- CSRF는 CSRF 토큰 사용 및 Referer 검증 등 방식으로 막을 수 있다.
JWT를 어디에 저장하는 것이 좋은 방법일까?
- JWT를 private variable에 저장하면, js variable은 페이지 새로고침 시 사라지는 휘발성이기 때문에 사용자 입장에서 화면 새로고침 시마다 로그인을 해야하는 불편함이 있다. 따라서 private variable에만 JWT를 저장하는 것은 피해야 한다.
- localStorage에 저장하는 방법
- CSRF 공격에 안전하다.
- 자동으로 request에 담기는 쿠키와 달리 js 코드에 의해 header에 담기므로, XSS를 뚫지 않는 이상 공격자가 정상적인 사용자인 척 request를 보내기 어려움
- 하지만, XSS에 취약하다.
- 공격자가 localStorage에 접근하는 JS 코드 한 줄만 주입하면 localStorage를 공격자가 내 집처럼 드나들 수 있다.
- CSRF 공격에 안전하다.
- Cookie에 저장하는 방법
- XSS 공격으로부터 localStorage에 비해 안전하다.
- 쿠키의 httpOnly 옵션을 이용하면 Js에서 쿠키에 접근 자체가 불가능하여, XSS 공격으로 쿠키 정보를 탈취할 수 없다.
- httpOnly 옵션은 서버에서 설정할 수 있으므로, 백엔드 api 에 내가 사용하는 쿠키를 위한 설정을 요청해야 한다. 하지만 서드파티 api를 사용하는 경우 백엔드와 조율할 수 없기에 localStorage를 사용하는 편이 나을 수 있다.
- 하지만 XSS 공격으로부터 완전히 안전한 것은 아니다.
- httpOnly 옵션으로 쿠키 내용을 볼 수 없다 해도 js로 request를 보낼 수 있으므로 자동으로 http request에 실리는 쿠키의 특성 상 사용자 컴퓨터에서 요청을 위조할 수 있다.
- 쿠키의 httpOnly 옵션을 이용하면 Js에서 쿠키에 접근 자체가 불가능하여, XSS 공격으로 쿠키 정보를 탈취할 수 없다.
- 하지만, CSRF 공경에 취약하다.
- XSS 공격으로부터 localStorage에 비해 안전하다.
가장 좋은 방법이 있다면?
refresh token을 사용하는 방법이 있다.
백엔드 api 개발자와 소통이 가능하다면, refresh token을 httpOnly 쿠키로 설정하고,
url이 새로고침 될 때마다, refresh token을 request에 담아 새로운 access token을 발급 받는다.
발급 받은 access token을 JS private variable에 저장한다.
이 방식을 사용하면, refresh token이 CSRF에 의해 사용된다 하더라도, 공격자는 access token을 알 수 없다.
CSRF는 요청을 위조하여 사용자가 의도하지 않은 서버 동작을 일으키는 공격 방법이기 때문에, refresh token을 통해 받아온 response(access token)은 공격자가 확인할 수 없다.
따라서, 쿠키를 사용해서 XSS를 막고, refresh token 방식을 이용하여 CSRF를 막을 수 있다.
※ 출처 『리액트를 다루는 기술 (개정판)』
320x100
반응형
'Devlog > Front-End' 카테고리의 다른 글
프론트엔드 프레임워크 비교(React, Vue, Angular), SPA란? (1) | 2022.08.30 |
---|---|
[React.js] Testing Library의 userEvent 사용 시 오류 (Error: Expected key descriptor but found "" in "") (0) | 2022.07.24 |
[React] '리액트를 다루는 기술' 스터디_3주차 (0) | 2022.05.27 |
[React] '리액트를 다루는 기술' 스터디_2주차 (Hooks) (0) | 2022.05.27 |
[React] '리액트를 다루는 기술' 스터디_1주차 (0) | 2022.05.27 |