JWT
JSON 객체를 사용해 서버와 클라이언트 간 정보를 안전하게 전송하는 공개 표준
JWT는 클라이언트나 악의적 공격자가 JSON 객체를 변경할 수 없도록 암호화(해싱)를 사용하여 서명된다.
구성요소
JWT는 . 을 구분자로 3가지의 문자열로 구성되어 있다.
xxxxx.yyyyy.zzzzz의 구조로 앞부터 헤더(header), 내용(payload), 서명(signature)로 구성된다.
헤더(Header)
헤더는 두가지 정보를 가진다.
• typ : 토큰의 타입을 지정함. JWT이기에 "JWT"라는 값이 들어간다.
• alg : 해싱 알고리즘을 지정한다. 토큰을 검증할 때 사용되는 signature 부분에서 사용된다.
* 해싱 : 가장 많이 쓰이는 암호화 방식 중 하나. 암호화만 가능하며 복호화가 불가능하다.
** 해싱 알고리즘은 주로 HMAC, SHA256, RSA 사용
{
"alg": "HS256",
"typ": "JWT"
}
이 JSON은 Base64Url 인코딩되어 JWT의 첫 번째 부분을 형성한다.
내용(Payload)
Payload는 클레임(claims)을 가진다.
claim은 정보의 한 조각, 즉 전달하려는 데이터를 의미한다.
- Json 형태(key-value)로 이루어져 있다.
- 한 토큰에는 여러 개의 클레임들을 넣을 수 있다.
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
payload는 Base64Url로 인코딩되어 JWT 두번째 부분에 위치한다.
클레임의 종류는 크게 세분류로 나누어진다
- 등록된 클레임, 공개 클레임, 비공개 클레임
등록된 클레임(Registered Claims)
서비스에서 필요한 정보들이 아닌, 토큰에 대한 정보들을 담기위하여 이름이 이미 정해진 클레임들이다.
등록된 클레임의 사용은 optional하지만, 사용을 권장한다.
- 등록된 클레임의 요소
iss : issuer, 토큰 발급자
exp : expiration time, 만료 시간
sub : subject, 토큰 제목
aud : audience, 토큰 대상자
공개 클레임(Public Claims)
사용자가 자유롭게 정의할 수 있다.
단, 충돌을 방지하려면 IANA JSON 웹 토큰 레지스트리에 정의돼 있거나 충돌이 방지된 네임스페이스를 포함하는 URI로 정의해야 한다.
비공개 클레임(Private Claims)
이는 등록된 또는 공개 클레임이 아닌 클레임이다.
정보를 공유하기 위해 만들어진 커스터마이징 클레임이다.
! 주의사항
서명된 토큰의 경우 이 정보는 변조로부터 보호되긴 하지만 누구나 읽을 수 있다.
암호화되지 않은 한 JWT의 payload 또는 header에 secret information을 넣지 말자!!
서명(Signature)
서명은 메세지가 도중에 변경되지 않았음을 증명하는데 사용된다.
서명을 만들기 위해선 인코딩된 header, payload와 secret, 그리고 header에 지정된 해싱 알고리즘이 필요하다.
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret
)
해싱 함수로 HMAC SHA256 알고리즘을 사용한다면, 서명은 위와 같은 방식으로 생성된다.