HTTP는 각 요청에 대해 매번 연결을 생성하고 끊는 비연결성, 그리고 요청에 대한 상태를 저장하지 않는 무상태성이라는 특징을 가진다. 불필요한 자원 낭비를 줄일 수 있는 장점이다.
하지만 서버는 클라이언트를 식별하지 못한다는 단점도 존재한다. 이번 요청으로 로그인에 성공해도, 상태를 저장하지 않기 때문에 이 클라이언트가 로그인했음을 기억하지 않는다.
이러한 단점을 해결하기 위해 쿠키와 세션을 사용한다. 쿠키는 클라이언트가 어떤 웹사이트를 방문할 경우, 그 사이트의 서버에 의해 클라이언트의 브라우저에 저장되는 key-value 형태의 정보 파일을 말한다.
이 쿠키를 통해 로그인 상태를 유지시킬 수 있지만, 쿠키는 브라우저에 저장되어 보안이 약하기 때문에 유출 및 조작 당할 위험이 존재한다.
세션은 정보를 브라우저가 아닌 서버 측에 저장하기 때문에 보안이 더 좋다. 인증 정보는 서버에 저장하고, 클라이언트 식별자인 JSESSIONID
를 쿠키에 담아, 클라이언트는 요청을 보낼 때마다 JSESSIONID
쿠키를 보내면 서버가 유효성을 판단해 클라이언트를 식별한다.
그럼에도 해커가 JSESSIONID
쿠키를 탈취하면 클라이언트인 척 위장이 가능하고, 서버에 부하가 갈 수 있다는 단점이 존재한다.
JWT(JSON Web Token)은 인증에 필요한 정보를 암호화시킨 토큰을 의미한다. 쿠키/세션 방식과 유사하게 JWT 토큰(Access Token)을 HTTP 헤더에 실어 서버가 클라이언트를 식별한다.
JWT는 .을 구분자로 세 개의 문자열로 나뉜다.
alg
와 typ
으로 각각 암호화할 해싱 알고리즘과 토큰의 타입을 지정한다{
"alg": "HS256",
"typ": "JWT"
}
key-value 형식으로, 한 쌍의 정보를 Claim이라 부른다
{
"sub": "12345812",
"name": "Hong Gildong",
"iat": 2385123
}
HMACSHA256(
base64URLEncode(header) + "." + base64URLEncode(payload), {256-bit-secret}
)
헤더와 페이로드는 단순히 인코딩된 값이기 때문에 제3자가 복호화 또는 조작할 수 있지만, Signature는 서버 측에서 관리하는 비밀키가 유출되지 않는 이상 복호화 할 수 없다. 따라서 Signature는 토큰의 위변조 여부를 확인하는데 사용된다.
Authorization
에 포함시켜 함께 전달한다Access Token과 함께 Refresh Token을 발급한다. Access Token을 탈취 당하면 기존 Access Token을 무효화 시킨 다음, 사용자는 다시 로그인해서 Access Token를 새로 발급 받는다.
하지만 서버는 Refresh Token을 별도의 저장소에 저장해야 하기 때문에 저장소가 필요없는 JWT의 장점을 완전히 누릴 수는 없다. 저장소에 저장한다는 건 처리하기 위해 I/O 작업을 수반한다는 의미기도 하다.
이 Refresh Token까지 탈취 당하면 안타깝다..
참고:
https://tecoble.techcourse.co.kr/post/2021-05-22-cookie-session-jwt/