14주차 토큰 JWT

lim1313·2021년 10월 21일
0

부트캠프 TIL

목록 보기
44/49

🌈 토큰기반 인증

토큰 기반의 인증 시스템은 인증받은 사용자들에게 토큰을 발급하고, 서버에 요청을 할 때 헤더에 토큰을 함께 보내도록 하여 유효성 검사를 한다. 이러한 시스템에서는 더이상 사용자의 인증 정보를 서버나 세션에 유지하지 않고 클라이언트 측에서 들어오는 요청만으로 작업을 처리한다. 즉, 서버 기반의 인증 시스템과 달리 상태를 유지하지 않으므로 Stateless한 구조를 갖는다. 이러한 토큰 기반의 인증 방식을 통해 수많은 문제점들을 해결할 수 있는데, 대표적으로 사용자가 로그인이 되어있는지 안되어있는지 신경쓰지 않고 손쉽게 시스템을 확장할 수 있다.

⚡ 토큰기반 인증의 장점

  • Statelessness & Scalability (무상태성 & 확장성)
    서버는 클라이언트에 대한 정보를 저장할 필요 없다 (토큰 해독이 되는지만 판단)
    토큰은 클라이언트 측에 저장되기 때문에 서버는 완전히 Stateless하며, 클라이언트와 서버의 연결고리가 없기 때문에 확장하기에 매우 적합하다. 만약 사용자 정보가 서버 측 세션에 저장된 경우에 서버를 확장하여 분산처리 한다면, 해당 사용자는 처음 로그인 했었던 서버에만 요청을 받도록 설정을 해주어야 한다. 하지만 토큰을 사용한다면 어떠한 서버로 요청이 와도 상관이 없다.

  • 안전하다
    암호화 한 토큰을 사용하고, 암호화 키를 노출 할 필요가 없기 때문에 안전하다

  • 어디서나 생성 가능하다
    토큰을 확인하는 서버가 토큰을 만들어야 하는 법이 없다
    토큰 생성용 서버를 만들거나, 다른 회사에서 토큰관련 작업을 맡기는 것 등 다양한 활용이 가능하다

  • 권한 부여에 용이하다
    토큰의 payload(내용물) 안에 어떤 정보에 접근 가능한지 정할 수 있다
    ex) 서비스의 사진과 연락처 사용권한만 부여


jwt 장점

인증 관련 정보를 DB에 저장한다면 이용자수가 늘어나는만큼 저장 공간이 더 많이 필요해진다. 또한 인증 시마다 DB를 사용하므로 인증이 몰리면 서버가 과부하될 위험이 있다.

반면 JWT는 별도 저장소가 필요치 않아 서버자원을 절약할 수 있고 인증 과정에서 다른 곳을 거칠 필요없어 효율적이다. 인증 정보를 가진 특정 서버에만 트래픽이 몰릴 일도 없다. 서버 부하를 줄이기 좋은 방식이다.

⚡ access token & refresh token

⚡ JWT 인증 과정

  • 클라이언트가 서버에 아이디/비밀번호를 담아 로그인 요청을 보낸다.
  • 아이디/비밀번호가 일치하는지 확인하고, 클라이언트에게 보낼 암호화된 토큰을 생성한다.
    • access/refresh 토큰을 모두 생성한다.
    • 토큰에 담길 정보(payload)는 유저를 식별할 정보, 권한이 부여된 카테고리(사진, 연락처, 기타등등)이 될 수 있다.
    • 두 종류의 토큰이 같은 정보를 담을 필요는 없다
  • 토큰을 클라이언트에게 보내주면, 클라이언트는 토큰을 저장한다.
    • 저장하는 위치는 local storage, cookie, react의 state 등 다양하다.
  • 클라이언트가 HTTP 헤더(authorization 헤더)에 토큰을 담아 보낸다.
    • bearer authentication을 이용한다.
  • 서버는 토큰을 해독하여 "아 우리가 발급해준 토큰이 맞네!" 라는 판단이 될 경우, 클라이언트의 요청을 처리한 후 응답을 보내준다.

🌈 토큰 저장 위치

1. localStorage / sessionStorage

첫 번째는 로그인 성공시 서버가 응답 정보에 토큰을 넣어서 전달하도록 하고, 해당 값을 웹 스토리지(localStorage 혹은 sessionStorage)에 넣고 다음부터 웹 요청을 할 때마다 HTTP 헤더 값에 넣어서 요청하는 방법이다.

sessionStorage

sessionStorage는 각 세션마다 데이터가 개별적으로 저장된다. 즉 여러 개의 탭을 실행 중이면 각 탭 별로 따로 데이터가 저장됩니다. 이 때 세션이 다르면 다른 세션의 sessionStorage에 접근할 수 없다.
sessionStorage에 데이터를 저장하고 가져오는 방법은 아래와 같다.

sessionStorage.setItem('myCat', 'Tom');
var myCat = sessionStorage.getItem('myCat');

localStorage

localStorage는 브라우저에 반영구적으로 저장된다. 브라우저를 종료해도 데이터가 유지되며 도메인 기준으로 저장을 한다.
A.com에서 B.com에 저장한 데이터를 접근할 수 없다.
localStorage에 데이터를 저장하고 가져오는 방법은 아래와 같다.

localStorage.setItem('myCat', 'Tom');
var myCat = localStorage.getItem('myCat');

이 방법은, 구현하기 쉽고, 하나의 도메인에 제한되어있지 않다는 장점이 있지만, XSS 해킹 공격을 통하여 해커의 악성스크립트에 노출이 되는 경우 매우 쉽게 토큰이 탈취 될 수 있다. 그냥 localStorage 에 접근하면 바로 토큰에 접근 할 수 있기 때문이다.

이에 대한 대안, 두번째 방식은 이 토큰을 쿠키에 넣는 것 이다.

2. 쿠키

쿠키를 설정할 때 httpOnly를 활성화 해주면, 자바스크립트로 토큰값에 접근하는 것을 막아준다. 오로지 HTTP 통신을 통해서만 쿠키가 전송된다. 따라서 웹 스토리지에서 발생할 수 있었던 XSS 공격을 막을 수 있다.Secure 옵션을 주면 HTTPS 로만 쿠키가 전송되기에 더 높은 보안수준을 만들 수 있다.

대신 쿠키는 CSRF 공격에 당할 수 있다는 위험성이 있지만, 이문제는 API에 대한 HTTP 요청을 특정함수를 통해서만 이루어지게 하는 방식으로 막을 수 있다. 그리고 HTTP 헤더에 Refer와 Origin 값을 통해서 엉뚱한 곳에서 오는 요청을 거부할 수도 있다. ???

하지만 쿠키는 한정된 도메인에서만 사용된다. 이 문제는 토큰이 필요해질 때 현재 쿠키에 있는 토큰을 사용하여 새 토큰을 문자열로 받아올 수 있게 하는 API를 구현하여 해결하면 된다. ???


jwt token 토큰 과제

profile
start coding

0개의 댓글