JWT (Json Web Token) 은
선택가능한 서명(signature) 방식 및 암호화 방식을 사용해 데이터를 만들기 위한 인터넷 표준(인터넷에 적용되는 기술이나 방법론) 말이 어려운데
당사자(보통 유저와 서버) 간에 정보를 JSON 개체로 간결하고 안전하게 전송하기 위한 규격 이라고 쉽게 설명할 수 있다.
다음과 같은 상황에 사용할 수 있다.
인증
권한 부여 (인가)
사용자가 로그인 후, 후속 요청에 JWT가 포함되고, 이를 검증하여 서버의 자원에 쉽게 액세스 할 수 있다.
정보 교환
서명을 통해 발신자가 누구인지 확인할 수 있고, 헤더와 페이로드를 사용하여 서명을 계산하므로 컨텐츠가 변조되지 않았음을 쉽게 확인할 수 있어 당사자 간에 정보를 안전하게 전송할 수 있다.
압축되어진 형태에서는 점(.)으로 구분된 3가지 파트로 구성되어 있다.
앞에서부터 헤더, 페이로드, 서명이다.
JWT는 URL 에서 파라미터로 사용가능하도록 (URL-Safe) Base64url 인코딩을 사용한다.
헤더(Header)
서명을 위해 어느 알고리즘을 사용하고, 토큰의 타입에 대한 부분으로 구성되어 있다.
{
"alg" : "HS256",
"typ" : "JWT"
}
페이로드(Payload)
토큰의 두번째 부분으로 클레임(claim)으로 구성되어 있는데
클레임이란 엔티티(보통 유저정보)나 추가적인 정보에 대한 설명을 말한다.
클레임에는 3개의 타입이 있다.
iss : 이 데이터의 발행자를 뜻합니다.
iat : 이 데이터가 발행된 시간을 뜻합니다.
exp : 이 데이터가 만료된 시간을 뜻합니다.
sub : 토큰의 제목입니다.
aud : 토큰의 대상입니다.
nbf : 토큰이 처리되지 않아야 할 시점을 의미합니다.
이 시점이 지나기 전엔 토큰이 처리되지 않습니다.
jti : 토큰의 고유 식별자입니다.
글자를 굳이 3개로 유지하는 이유가 정보를 간결(compact) 함을 유지하기 위함이라고 한다.
Public claims
사용자 마음대로 쓸 수 있으나 충돌 방지를 위해 IANA(인터넷 할당 번호 관리기관)에서 지정한 것을 사용하는게 좋다.
Private claims
통신 하는 당사자끼리 자유롭게 정보를 교환하게 사용할 수 있는 것으로 Registered와 Public에 등록되지 않는 것이다.
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
주의 해야 할 점은 단순하게 Base64Url로 인코딩 했을 뿐 암호화 된 정보가 아니므로 보안과 관련된 정보를 넣어서는 안된다. 탈취된 경우 쉽게 정보를 볼 수 있기 때문이다.
서명(Signature)
메시지가 도중에 변경되지 않았는지 확인하는 데 사용되는데
base64Url로 인코딩 된 헤더, base64Url로 인코딩 된 페이로드, 암호(secret)의 조합을 선택된 암호화 알고리즘을 통해 암호화 되어 있다.
선택한 알고리즘 종류에 따라 키의 종류가 늘어날 수 있다.
아래의 경우 HMAC SHA256 알고리즘을 사용할 때 다음과 방식으로 생성이 된다.
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
JSON(JavaScript Object Notation) 형식은 XML(eXtensible Markup Language)
보다 가독성이 좋은 것 뿐만 아니라 인코딩 될 때 크기가 작아져서
HTML 및 HTTP 환경에서 데이터를 쉽게 전달할 수 있다.
인증의 경우에서 유저가 로그인을 완료하면 JWT 토큰이 반환되는데
토큰은 로그인에 성공했음을 증명하는 데이터이므로 탈취 당하지 않도록 주의해야 한다.
또한 토큰을 요구된 것보다 오래 보관해서는 안된며
보안에 취약한 HTML5의 Local storage 같은 곳에 보관해서는 안된다.
(httpOnly, secure 옵션이 켜진 쿠키에 저장하자.)
보호된 경로나 자원에 유저가 접근할 때 마다
클라이언트에서 JWT를 서버로 보내는데
보통 Authorization 헤더에 Bearer 스키마를 사용하여 전달한다.
Authorization: Bearer <token>
서버는 Authorization 헤더에 유효한 JWT 토큰이 맞는지 확인할 것이다.
JWT가 필수적인 데이터를 들고 있으면, 매번 데이터베이스에 쿼리해야 작업들을 줄일 수 있다.
주의해야 할 점은 HTTP 헤더로 전달하는 경우에는 크기가 너무 크지 않도록 주의 해야 한다. 서버가 8KB 이상의 헤더를 받지 못하는 경우가 있다.
Authorization 헤더를 통해 토큰이 보내진다면, 쿠키를 사용하지 않기 때문에 CORS(Cross-Origin Resource Sharing)이 발생하지 않을 것이다.
참조한 책 및 사이트
https://ko.wikipedia.org/wiki/JSON_%EC%9B%B9_%ED%86%A0%ED%81%B0
https://velog.io/@cmin95/JWT-Json-Web-Token
https://seahrin.com/entry/Base64-Encoding-%EC%99%80-Base64Url-Encoding-%EA%B3%BC%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90
https://vvshinevv.tistory.com/103