토큰 기반의 인증 시스템은 인증받은 사용자들에게 토큰을 발급하고, 서버에 요청을 할 때 헤더에 토큰을 함께 보내도록 하여 유효성 검사를 한다. 이러한 시스템에서는 더이상 사용자의 인증 정보를 서버나 세션에 유지하지 않고 클라이언트 측에서 들어오는 요청만으로 작업을 처리한다. 즉, 서버 기반의 인증 시스템과 달리 상태를 유지하지 않으므로 Stateless한 구조를 갖는다. 이러한 토큰 기반의 인증 방식을 통해 수많은 문제점들을 해결할 수 있는데, 대표적으로 사용자가 로그인이 되어있는지 안되어있는지 신경쓰지 않고 손쉽게 시스템을 확장할 수 있다.
Statelessness & Scalability (무상태성 & 확장성)
서버는 클라이언트에 대한 정보를 저장할 필요 없다 (토큰 해독이 되는지만 판단)
토큰은 클라이언트 측에 저장되기 때문에 서버는 완전히 Stateless하며, 클라이언트와 서버의 연결고리가 없기 때문에 확장하기에 매우 적합하다. 만약 사용자 정보가 서버 측 세션에 저장된 경우에 서버를 확장하여 분산처리 한다면, 해당 사용자는 처음 로그인 했었던 서버에만 요청을 받도록 설정을 해주어야 한다. 하지만 토큰을 사용한다면 어떠한 서버로 요청이 와도 상관이 없다.
안전하다
암호화 한 토큰을 사용하고, 암호화 키를 노출 할 필요가 없기 때문에 안전하다
어디서나 생성 가능하다
토큰을 확인하는 서버가 토큰을 만들어야 하는 법이 없다
토큰 생성용 서버를 만들거나, 다른 회사에서 토큰관련 작업을 맡기는 것 등 다양한 활용이 가능하다
권한 부여에 용이하다
토큰의 payload(내용물) 안에 어떤 정보에 접근 가능한지 정할 수 있다
ex) 서비스의 사진과 연락처 사용권한만 부여
인증 관련 정보를 DB에 저장한다면 이용자수가 늘어나는만큼 저장 공간이 더 많이 필요해진다. 또한 인증 시마다 DB를 사용하므로 인증이 몰리면 서버가 과부하될 위험이 있다.
반면 JWT는 별도 저장소가 필요치 않아 서버자원을 절약할 수 있고 인증 과정에서 다른 곳을 거칠 필요없어 효율적이다. 인증 정보를 가진 특정 서버에만 트래픽이 몰릴 일도 없다. 서버 부하를 줄이기 좋은 방식이다.
local storage
, cookie
, react의 state
등 다양하다.authorization 헤더
)에 토큰을 담아 보낸다.bearer authentication
을 이용한다.첫 번째는 로그인 성공시 서버가 응답 정보에 토큰을 넣어서 전달하도록 하고, 해당 값을 웹 스토리지(localStorage 혹은 sessionStorage)에 넣고 다음부터 웹 요청을 할 때마다 HTTP 헤더 값에 넣어서 요청하는 방법이다.
sessionStorage는 각 세션마다 데이터가 개별적으로 저장된다. 즉 여러 개의 탭을 실행 중이면 각 탭 별로 따로 데이터가 저장됩니다. 이 때 세션이 다르면 다른 세션의 sessionStorage에 접근할 수 없다.
sessionStorage에 데이터를 저장하고 가져오는 방법은 아래와 같다.
sessionStorage.setItem('myCat', 'Tom');
var myCat = sessionStorage.getItem('myCat');
localStorage는 브라우저에 반영구적으로 저장된다. 브라우저를 종료해도 데이터가 유지되며 도메인 기준으로 저장을 한다.
A.com에서 B.com에 저장한 데이터를 접근할 수 없다.
localStorage에 데이터를 저장하고 가져오는 방법은 아래와 같다.
localStorage.setItem('myCat', 'Tom');
var myCat = localStorage.getItem('myCat');
이 방법은, 구현하기 쉽고, 하나의 도메인에 제한되어있지 않다는 장점이 있지만, XSS 해킹 공격을 통하여 해커의 악성스크립트에 노출이 되는 경우 매우 쉽게 토큰이 탈취 될 수 있다. 그냥 localStorage 에 접근하면 바로 토큰에 접근 할 수 있기 때문이다.
이에 대한 대안, 두번째 방식은 이 토큰을 쿠키에 넣는 것 이다.
쿠키를 설정할 때 httpOnly
를 활성화 해주면, 자바스크립트로 토큰값에 접근하는 것을 막아준다. 오로지 HTTP 통신을 통해서만 쿠키가 전송된다. 따라서 웹 스토리지에서 발생할 수 있었던 XSS 공격을 막을 수 있다.Secure 옵션을 주면 HTTPS 로만 쿠키가 전송되기에 더 높은 보안수준을 만들 수 있다.
대신 쿠키는 CSRF 공격에 당할 수 있다는 위험성이 있지만, 이문제는 API에 대한 HTTP 요청을 특정함수를 통해서만 이루어지게 하는 방식으로 막을 수 있다. 그리고 HTTP 헤더에 Refer와 Origin 값을 통해서 엉뚱한 곳에서 오는 요청을 거부할 수도 있다. ???
하지만 쿠키는 한정된 도메인에서만 사용된다. 이 문제는 토큰이 필요해질 때 현재 쿠키에 있는 토큰을 사용하여 새 토큰을 문자열로 받아올 수 있게 하는 API를 구현하여 해결하면 된다. ???