Welcome :っ)

Devlog/Front-End

[React] '리액트를 다루는 기술' 스터디_4주차 (JWT의 이해)

lazy.won 2022. 5. 27. 09:06
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, 변수 값 등 모든 것이 탈취 가능하기 때문이다.
  • 브라우저의 쿠키에 담아서 사용하는 방법 
    • httpOnly 속성을 활성화하여 자바스크립트를 통해 쿠키를 조회할 수 없으므로 악성 스크립트로부터 안전하다.
    • 대신, 토큰을 쿠키에 담으면 사용자가 서버 요청할 때마다 무조건 토큰이 함께 전달되는 점을 이용하여 사용자 모르게 원치 않는 api 요청을 하게 만드는 CSRF 공격에 취약하다.
      • CSRF(Cross Site Request Forgery) 공격
        • request를 가로채 사용자인 척 하고 백엔드 서버에 변조된 request를 보내 악의적인 동작을 수행하는 공격이다. (사용자 정보 수정 및 정보 열람) 
        • XSS를 막으면 CSRF도 막을 수 있는가?
          • 아니다. 사용자 브라우저의 js를 조작하여 공격하는 XSS와 성격이 다르다. 이미지 태그나 링크로도 사용자 브라우저에서 악의적인 request를 보낼 수 있다. 
    • CSRF는 CSRF 토큰 사용 및 Referer 검증 등 방식으로 막을 수 있다. 

 

 

 

JWT를 어디에 저장하는 것이 좋은 방법일까?

  • JWT를 private variable에 저장하면, js variable은 페이지 새로고침 시 사라지는 휘발성이기 때문에 사용자 입장에서 화면 새로고침 시마다 로그인을 해야하는 불편함이 있다. 따라서 private variable에만 JWT를 저장하는 것은 피해야 한다. 
  • localStorage에 저장하는 방법
    • CSRF 공격에 안전하다. 
      • 자동으로 request에 담기는 쿠키와 달리 js 코드에 의해 header에 담기므로, XSS를 뚫지 않는 이상 공격자가 정상적인 사용자인 척 request를 보내기 어려움
    • 하지만, XSS에 취약하다.
      • 공격자가 localStorage에 접근하는 JS 코드 한 줄만 주입하면 localStorage를 공격자가 내 집처럼 드나들 수 있다. 
  • Cookie에 저장하는 방법
    • XSS 공격으로부터 localStorage에 비해 안전하다.
      • 쿠키의 httpOnly 옵션을 이용하면 Js에서 쿠키에 접근 자체가 불가능하여, XSS 공격으로 쿠키 정보를 탈취할 수 없다.
        • httpOnly 옵션은 서버에서 설정할 수 있으므로, 백엔드 api 에 내가 사용하는 쿠키를 위한 설정을 요청해야 한다. 하지만 서드파티 api를 사용하는 경우 백엔드와 조율할 수 없기에 localStorage를 사용하는 편이 나을 수 있다.
      • 하지만 XSS 공격으로부터 완전히 안전한 것은 아니다. 
        • httpOnly 옵션으로 쿠키 내용을 볼 수 없다 해도 js로 request를 보낼 수 있으므로 자동으로 http request에 실리는 쿠키의 특성 상 사용자 컴퓨터에서 요청을 위조할 수 있다. 
    • 하지만, CSRF 공경에 취약하다.

 

 

가장 좋은 방법이 있다면?

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
반응형