JWT(Json Web Token)란 Json 포맷을 이용하여 사용자에 대한 속성을 저장하는 Claim 기반의 Web Token이다. JWT는 토큰 자체를 정보로 사용하는 Self-Contained 방식으로 정보를 안전하게 전달한다.
JWT는 세 개의 점으로 구분된 문자열로 표현되며, 세 가지 부분으로 구성됩니다: Header (헤더), Payload (페이로드), Signature (서명). 각 부분은 Base64 인코딩되어 표현되며, 각 부분은 점(.)으로 구분됩니다.
Header 에는 JWT 에서 사용할 타입과 해시 알고리즘의 종류가 담겨있으며, Payload 는 서버에서 첨부한 사용자 권한 정보와 데이터가 담겨있다. 마지막으로 Signature는 Header, Payload에 서버의 secret key와 Header에 명시된 해시함수를 서명해서 만든다.
payload는 인코딩 되어 있을 뿐 암호화가 되어있지 않다. 그러므로 민감한 정보는 넣으면 안된다.
유저 JWT: A(Header) + B(Payload) + C(Signature) 일 때 (만일 임의의 유저가 B를 수정했다고 하면 B'로 표시한다.)
다른 유저가 B를 임의로 수정 -> 유저 JWT: A + B' + C
수정한 토큰을 서버에 요청을 보내면 서버는 유효성 검사 시행
유저 JWT: A + B' + C
서버에서 검증 후 생성한 JWT: A + B' + C' => (signature) 불일치
대조 결과가 일치하지 않아 유저의 정보가 임의로 조작되었음을 알 수 있다.
정리하자면, 서버는 토큰 안에 들어있는 정보가 무엇인지 아는게 중요한 것이 아니라 해당 토큰이 유효한 토큰인지 확인하는 것이 중요하기 때문에, 클라이언트로부터 받은 JWT의 헤더, 페이로드를 서버의 key값을 이용해 시그니처를 다시 만들고 이를 비교하며 일치했을 경우 인증을 통과시킨다.
expire time이 커지면 login timeout이 발생할 가능성이 낮아진다. 하지만 공격자가 탈취했을 때 무언가(?)를 할 시간이 많아진다.
expire time이 작아지면 보안에는 좋지만 login timeout이 빈번하게 일어날 것이다.
처음에 JWT를 접했을 때 Refresh Token이 왜 있는건지 이해가 가지 않았다. Access token의 expire time을 짧게 가져가기 위해서라고 했다. 하지만 로그인했을 때 어차피 Access token과 Refresh token을 동시에 발급해주는거라면 access token과 마찬가지로 refresh token도 탈취당하는 것 아닌가?라는 생각이 있었다.
token이 위험한 경우는 위에서 말한대로 token이 공격자에게 탈취당했을 때이다. 그 탈취는 주로 web상에서 공격자가 intercept해서 발생하다. 그리고 expire time이 짧은 access token이 주로 request에 쓰이며 돌아다니게 하고 expire time이 긴 refresh token은 client의 local storage에 꽁꽁 숨겨두려고 하는 의도이다. expire time 자체를 짧게 가져가는 것도 하나의 방법이 되겠지만 위에서 말한대로 login timeout과 trade off가 있다.