
인증은 사용자가 누구인지 확인하는 과정이다. 예) 로그인, 비밀번호 확인
로그인에 성공하면 서버는 응답으로 사용자에게 토큰을 전달한다. 로그인에 실패한 사용자는 토큰을 전달받지 못해 원하는 리소스에 접근할 수 없게 된다.
인가는 인증을 통과한 사용자가 애플리케이션 내 특정 리소스에 접근할 권한이 있는지를 확인하는 과정이다. 예) 게시판 접근 등급 확인
일반적으로 인증 단계에서 발급된 토큰에는 인가 정보가 함께 포함된다. 사용자가 리소스에 접근할 때 이 토큰을 서버에 전달하면, 서버는 토큰을 검증해 접근 권한이 있는지를 판별한다.
사용자의 로그인 상태를 서버에서 관리하는 방식은 크게 세션 기반 인증과 토큰 기반 인증으로 나눌 수 있다.

세션 기반 인증에서 사용자가 로그인하면 서버는 세션 저장소에 사용자 정보를 기록하고 세션 id를 발급한다.
이 세션 id는 주로 브라우저의 쿠키에 저장되며, 사용자가 요청을 보낼 때마다 함께 전송된다.
서버는 세션 저장소에서 세션 id를 조회해 로그인 여부를 확인하고 요청을 처리한다. 세션 저장소로는 주로 메모리, 디스크, 데이터베이스 등을 사용된다.
세션 기반 인증은 서버를 확장하기가 번거로워질 수 있다. 만약 서버의 인스턴스가 여러 개가 된다면 모든 서버끼리 같은 세션을 공유해야 하므로 세션 전용 데이터베이스를 만들어야 할 뿐 아니라 신경 써야 할 것도 많다.
토큰은 로그인 시 서버가 발급하는 문자열이다. 여기에는 사용자 정보와 함께, 해당 정보가 서버에서 발급되었음을 보장하는 서명(Signature)이 들어 있다.
이 서명은 해싱 알고리즘으로 생성되며, 덕분에 토큰의 무결성이 보장된다. 무결성이란 정보가 변경되거나 위조되지 않았음을 의미하는 성질이다.

사용자가 로그인하면 서버는 해당 사용자의 정보를 지니고 있는 토큰을 발급하고, 이후 요청마다 사용자가 이 토큰을 포함해 요청한다. 서버는 해당 토큰이 유효한지 검사하고 요청을 처리한다.
세션 방식과 달리 서버는 로그인 상태를 따로 저장하지 않기 때문에 확장성이 높다. 서버 인스턴스가 여러 개여도, 각 서버가 토큰만 검증하면 되므로 상태 공유가 필요 없다.
사용자가 브라우저에서 토큰을 사용할 때는 주로 두 가지 방법을 사용한다. 첫 번째는 브라우저의 로컬 스토리지 혹은 세션 스토리지 담아서 사용하는 방법이고, 두 번째는 브라우저의 쿠키에 담아서 사용하는 방법이다.
로컬 스토리지: 새로고침·브라우저 재시작 후에도 유지
세션 스토리지: 새로고침 시 유지, 탭 종료 시 삭제
로컬 스토리지 혹은 sessionStorage에 토큰을 담으면 사용하기 편리하고 구현하기도 쉽다. 하지만 만약 누군가가 페이지에 악성 스크립트를 삽입하면 쉽게 토큰을 탈취할 수 있다. 이러한 공격을 XSS(Cross Site Scripting)라고 부른다.
쿠키에 담아도 같은 문제가 발생할 수 있지만 httpOnly라는 속성을 활성화하면 자바스크립트를 통해 쿠키를 조회할 수 없으므로 악성 스크립트로부터 안전하다. 대신 CSRF(Cross Site Request Forgery)라는 공격에 취약할 수 있다. 이 공격은 토큰을 쿠키에 담으면 사용자가 서버로 요청할 때마다 무조건 토큰이 함께 전달되는 점을 이용해서 사용자가 모르게 원하지 않은 API 요청을 하게 만든다.
단, CSRF는 CSRF 토큰 사용 등의 방식으로 제대로 막을 수 있는 반면, XSS는 보안장치를 적용해 놓아도 개발자가 놓칠 수 있는 다양한 취약점을 통해 공격을 받을 수 있다.
JWT는 정보를 JSON 형태로 안전하게 전송하기 위한 토큰이다. JWT는 URL로 이용할 수 있는 문자열로만 구성되어 있기 때문에 HTTP 구성요소 어디든 위치할 수 있다. 또한 디지털 서명이 적용되어 있어 신뢰할 수 있다. 주로 서버와의 통신에서 권한 인가를 위해 사용된다.
JWT는 점(.)으로 구분된 아래의 세 부분으로 구성된다.

검증과 관련된 내용을 담고 있다. alg와 typ 속성을 포함한다.
완성된 헤더는 Base64Url 형식으로 인코딩되어 사용된다.
토큰에 담는 정보를 포함한다. 이곳에 포함된 속성들은 클레임(Claim)이라 하며 크게 세 가지로 분류된다.
완성된 내용은 Base64Url 형식으로 인코딩되어 사용된다.
암호화된 것이 아니기 때문에 중간에 payload를 탈취하여 디코딩하면 데이터를 볼 수 있다. 따라서 JWE로 암호화하거나 payload에 중요한 데이터를 넣지 않아야 한다.
서명은 인코딩된 헤더, 인코딩된 내용, 비밀키, 헤더의 알고리즘 속성값을 가져와 생성된다.
서명은 토큰의 값들을 포함해서 암호화하기 때문에 메시지가 도중에 변경되지 않았는지 확인할 때 사용된다.

클라이언트의 로그인 정보를 서버에 저장하지 않기 때문에 토큰 기반 인증 메커니즘을 제공한다.
JWT에는 필요한 모든 정보를 토큰에 포함하기 때문에 데이터베이스와 같은 서버와의 커뮤니케이션 오버 헤드를 최소화할 수 있다.
.
.
.
참고)
리액트를 다루는 기술
스프링 부트 핵심 가이드
https://ivory-room.tistory.com/88