JWT(Json Web Token)는 JSON을 사용해 가볍고 자가 수용적인 방식으로 정보를 안전성 있게 전달해 주는 토큰이다. 주로 회원 인증이나 정보 교류에 사용된다.
자가 수용적(self-contained) : 필요한 정보를 자체적으로 지니고 있다. 즉, JWT 토큰은 토큰에 대한 정보 유저 정보 등이 들어 있다. 또한, 토큰이 위조되지 않았다는 것을 증명할 signature를 포함하고 있다.
이전에는 주로 session을 이용한 인증 방식을 사용했다. 세션 기반 인증 방식은 서버 측에서 인증된 유저들의 정보를 메모리나 DB에 저장해 요청이 들어올 때 저장된 정보를 꺼내 사용한다.
하지만 이런 방식에는 소규모 시스템에서는 문제가 잘 보이지 않지만, 유저 수가 많아지면서 서버를 확장하기 시작하면 문제가 발생한다. 로그인 중인 사용자가 늘어나면서 서버의 메모리나 DB에 무리를 줄 수 있고, 서버를 확장하기 어려워진다.
이런 문제를 해결하기 위해 토큰 기반 인증을 사용하게 되었다. 토큰 기반 인증 방식은 인증된 사용자에게 토큰을 발급하고, 서버에 요청을 할 때 토큰을 함께 보내는 방식이다. 이 방식을 사용하면 인증된 사용자 정보를 서버에 저장하지 않아도 되기 때문에 서버 자원 절약이 가능하고, 서버 확장에도 유리하다.
JWT 토큰은 기본적으로 header, payload, signature로 나누어져 있고, 세 부분을 .
으로 연결해 놓은 형태이다.
{
"alg": "HS256",
"typ": "JWT"
}
header에는 토큰 자체에 대한 정보가 포함되어 있다.
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
payload에는 토큰에 담을 정보가 포함되어 있다. 여기에 담는 정보의 한 조각을 클레임(claim)이라고 하고, 이는 key/value 형태의 한 쌍으로 이루어져 있다. 클레임의 종류는 registered 클레임, public 클레임, private 클레임으로 나뉘어져 있다.
registered claim은 토큰에 대한 정보를 저장하기 위해 이미 이름이 정해진 클레임이다. 클레임 사용은 모두 optional이다.
public claim은 충돌 방지된 이름을 가지고 있어야 한다. 주로 URI 형태로 작성한다.
{
"https://susemeeee.com/admin": false
}
private claim은 클라이언트 - 서버 간 협의하에 사용되는 클레임 이름이다. public claim과는 달리 이름이 중복 가능하다.
{
"custom1": "qwerty"
"custom2": 3
"custom3": true
}
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret
)
signature은 토큰을 인코딩하거나 유효성 검증 시 사용되는 고유한 암호화 코드이다. 앞서 만들어진 header, payload를 Base64 URL-safe 인코딩한 이후 header에 적힌 해시 함수를 적용해 서버 개인 키로 서명한다.