리눅스·서버 학습

JWT 구조와 안전하게 쓰는 방법

JWT가 어떻게 생겼는지, 어디에 저장하고 무엇을 넣으면 안 되는지 정리했습니다.

JWT는 점으로 구분된 세 부분입니다. 헤더는 알고리즘, 페이로드는 사용자 정보와 만료 시각, 서명은 위조 방지를 담습니다. 앞의 두 부분은 Base64URL 인코딩일 뿐이라 누구나 읽을 수 있습니다.

서명이 하는 일

서버는 비밀키로 서명을 만들고, 요청이 올 때 다시 계산해 비교합니다. 내용을 바꾸면 서명이 맞지 않아 거부됩니다. 서명은 내용을 숨기지 않습니다. 비밀번호나 주민번호 같은 값을 페이로드에 넣으면 안 됩니다.

꼭 검증할 항목

  • 알고리즘을 서버에서 고정합니다. 토큰 헤더의 alg를 그대로 믿으면 none 공격에 노출될 수 있습니다.
  • exp를 확인하고 액세스 토큰은 짧게 유지합니다.
  • iss와 aud를 확인해 다른 서비스용 토큰을 거부합니다.
  • 서명 키는 충분히 길고 무작위여야 합니다.

어디에 저장할까

localStorage는 쓰기 쉽지만 XSS가 생기면 스크립트가 토큰을 읽을 수 있습니다. HttpOnly, Secure, SameSite 쿠키는 스크립트가 읽을 수 없는 대신 CSRF를 고려해야 합니다. 어느 쪽이든 XSS를 막는 것이 우선이고, 짧은 액세스 토큰과 교체되는 리프레시 토큰을 함께 쓰면 피해를 줄일 수 있습니다.

로그아웃이 어려운 이유

JWT는 서버가 상태를 저장하지 않으므로 발급된 토큰을 바로 무효로 만들기 어렵습니다. 그래서 만료를 짧게 두고, 리프레시 토큰은 서버에 저장해 폐기할 수 있게 하는 구성을 많이 씁니다.

JWT 해석기