JWT를 이용해서 안전하게 사용자를 인증할 수 있는 이유
JWT의 구성 요소
- JWT는 다음의 세 가지 구성 요소로 이루어져 있다:
- 헤더(Header), 페이로드(Payload), 서명(Signature)
- 서버가 클라이언트에게 JWT를 발급할 때, 서명(Signature)에는 (헤더 + 페이로드 + 서버의 비밀 키)를 해싱한 값이 담긴다. 이때 발급한 토큰은 보통
(A.B.C)
형식으로 표현된다.
JWT 서명 검증의 동작 원리
- 클라이언트가 헤더나 페이로드를 수정하지 않았다면, 서명 값 C는 변하지 않는다. 따라서 클라이언트는 서버로부터 받은
A.B.C
형태의 JWT를 그대로 요청 시 함께 전송한다. - 서버는 클라이언트가 보낸 JWT에서 헤더 A와 페이로드 B를 추출한 후, 서버에 저장된 비밀 키와 함께 다시 해싱을 수행해 서명 값을 계산한다. 이는 처음 JWT를 생성할 때 사용한 방식과 동일하다.
- 이후 서버는 클라이언트가 보낸 JWT에 포함된 서명(C)과 자신이 다시 계산한 서명을 비교한다. 두 서명이 일치하면 해당 토큰이 유효하다고 판단한다.
토큰 변조 시 어떤 일이 일어날까?
- 클라이언트가 페이로드를 임의로 수정했다고 가정하자. 이 경우 토큰은
A.B'.C'
와 같은 형태가 된다. - 앞서 설명했듯이 서명은 (헤더 + 페이로드 + 비밀 키) 조합으로 생성되므로, 클라이언트가 서버의 비밀 키를 모른 채 서명을 다시 만든다면 원래의 서명(C)과는 다른 값(C’)가 생성된다.
- 서버는 클라이언트가 보낸 토큰에서 A와 B’를 추출하고, 서버의 비밀 키를 사용해 서명을 다시 계산한다. 하지만 이 서명은 클라이언트가 만든 C’와 다르기 때문에, 서버는 해당 토큰이 변조되었음을 감지할 수 있다.
결론
클라이언트가 헤더나 페이로드를 임의로 변경해도, 비밀 키를 모르면 동일한 서명을 생성할 수 없다. 이 덕분에 서버는 클라이언트가 보낸 JWT가 변조되었는지 검증할 수 있으며, 이는 JWT가 안전한 인증 수단으로 사용될 수 있는 핵심적인 이유다.