참조: https://www.youtube.com/watch?v=1QiOXWEbqYQ
JWT
- 로그인: 보안에 직결
- 로그인 상태를 유지 → 토큰, 세션
인증 vs 인가
- 인증(Authentication): 로그인
- 인가(Authorization)
- 한번 인증받은 사용자가 페이지의 기능을 사용할 때 허가해주는 것
로그인 상태 확인
- 로그인과 인증을 거친 상태인지 확인
- 요청마다 아이디와 패스워드를 확인하는 것은 오버헤드가 크다.
세션
- 로그인에 성공하면 서버와 브라우저에 데이터를 저장
- 서버가 재부팅되는 상황일 경우 데이터가 다 날아감
- 메모리나 하드디스크, DB에 저장
- 분산된 서버에서 처리할 경우 세션 유지가 어려움
JWT
- 서버가 복잡한 구성과 환경에서 어떤 상태를 기억해야 되는 리스크를 해소하기 위한 방법
- 토큰 방식
- 사용자가 로그인을 할 경우 토큰을 브라우저에게 주고 서버에서는 기억하지 않음
- 마침표로 끊어서 3부분으로 나누어짐
- header, payload, verify signature
- 페이로드(Base64 인코딩)
- 토큰 발행자
- 토큰 유효 기간
- 공개하는 내용
- Claim: 토큰에 담긴 사용자 정보 등의 데이터
- 사용자가 로그인 후 토큰(claim이 담겨짐, 관리자 여부 등)을 받음 → 이후 요청에서는 사용자로부터 서버로 전송됨(서버가 정보를 찾아야되는 일이 줄어듬)
- 헤더
- type: 토큰의 타입으로 언제나 JWT
- alg: 알고리즘의 약자로 서명값을 만드는 알고리즘이 지정됨(HS256 등)
- 헤더와 페이로드, 서버에 감춰놓은 비밀 값 이 셋을 alg에 넣고 돌리면 서명값이 나옴
- 한쪽 방향에서만 계산이 가능해서 서버만 알 수 있음
- 서버는 요청에 토큰 값이 실려오면 헤더와 페이로드의 값을 비밀 값과 함께 돌려봐서 계산된 결과값이 서명값과 일치하는지 확인
- 조금이라도 조작된 경우 일치하지 않음
- 계산된 결과값과 서명값이 일치하고 유효한 기간 내의 토큰일 경우 인가
- 서버는 사용자의 상태를 따로 기억할 필요가 없이 비밀 값만 알고 있으면 됨
- Stateless
- 단점
- 세션처럼 모든 사람의 상태를 기억
- 구현하기 부담되고 고려사항이 많음
- 기억하는 대상의 상태들을 언제든 제어 가능
- 한 기기에서만 로그인이 가능한 서비스를 만드는 경우, PC에서 로그인한 사람이 모바일에서 로그인하면 PC의 세션을 종료할 수 있음
- JWT 에서는 사용자의 정보를 가지고 있지 않기 때문에 제어할 수 없음
- 악의적인 사용자가 토큰을 빼앗아가버릴 경우 이를 무효화 할 수 있는 방법이 없음
- 실서비스에서 JWT 만으로 인가를 구현하는 경우는 잘 없음
- 이러한 문제를 해결하기 위해 토큰의 수명을 짧게함
- 로그인 시 2개의 토큰을 제공
- 수명이 몇 시간이나 몇 분 이하로 짧은 access 토큰 발급
- 길게 2주 정도 잡힌 refresh 토큰 발급
- refresh 토큰은 서버의 데이터베이스에 저장하여 access 토큰이 만료될 경우 refresh 토큰 값을 비교하여 일치할 경우 새 access 토큰을 발급해줌
- refresh 토큰만 안전하게 관리한다면 이게 유효할 동안은 access 토큰이 만료될 때마다 다시 로그인할 필요가 없음