HTTP는 무상태성(stateless) 프로토콜이기 때문에, 누가 요청했고, 누가 인증된 클라이언트인지 알 수 없다. 따라서 서버에 클라이언트의 접속 상태를 저장하는 것이 세션 기반 인증이다.
서버는 세션 storage에 클라이언트는 주로 쿠키에 세션 값을 저장한다. 클라이언트에서 요청이 들어오면 세션 storage에서 확인하여 유효한 세션인지 확인한다.
사용자의 인증 정보를 토큰에 담아 서버로 전달한다. 서버는 토큰에 담긴 사용자 정보를 따로 저장하지 않고 바로 검증한다. 사용자 인증이 된다면 클라이언트에 공개/개인 키를 이용해 서명한 토큰을 클라이언트에 전달한다.
클라이언트는 데이터 요청을 할 때 해당 토큰을 주로 헤더에 담아 요청을 날린다. 서버는 이 토큰이 유효한지 확인 후 반응을 보낸다.
인증에 필요한 정보를 토큰에 담아 암호화 시켜 사용한다. 데이터들은 JSON의 형태로 작성되며, 비밀키 또는 공개/개인 키로 서명하여 사용한다. 공개/개인 키를 사용함을써 송신자를 특정할 수 있고, 데이터의 무결성도 확인할 수 있다.
Header
→ 토큰의 타입과 서명에 사용된 알고리즘을 명시한다.
{
"typ": "JWT",
"alg": "HS256"
}
Payload
→ 토큰에 대한 property를 key-value로 저장하며, 이 데이터 하나하나를 claim이라고 한다.
{
"sub": "1",
"iss": "ori",
"exp": 1636989718,
"iat": 1636989718,
}
주의: payload에는 민감한 정보를 담지 않는다.
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secretkey
)
JWT의 알고리즘 타입 중 none이 있는데, 이 알고리즘은 서명 값 검증을 하지 않는다.
none 알고리즘을 허용할 경우 악의적 사용자가 서명 없이 토큰을 생성해 인증 절차를 우회하여 데이터에 접근 할 수 있다.
→ 이 위험을 줄이기 위해 none 알고리즘을 이용한 서명 없는 토큰은 사용할 수 없게 막아야 한다.
서명 키 값을 획득한다면 페이로드의 데이터를 변조하여 유효한 토큰을 생성할 수 있다.
이를 이용해 악의적 행위가 가능하다.
→ 이 위험을 줄이기 위해 복잡도가 높은 비밀키를 사용해 토큰을 암호화하여야 한다.
토큰의 서명을 이용해 검증하면 토큰의 만료 시점까지 사용이 가능하다. 토큰이 중간에 탈취될 경우 만료될 때까지 악의적으로 사용될 위험이 있다.
→ 이 위험을 줄이기 위해 Access 토큰과 Refresh 토큰을 사용한다.