JSON Web Token
의 약자로 모바일이나 웹에서 클라이언트와 서버 간 통신 시 사용자의 인증을 위해 사용하는 암호화된 토큰을 의미한다.
JWT 정보는 주로 통신 시 헤더의 Authorization
에 담아 전송되며 이것을 서버에서 검증하여 사용자의 정보 열람, 권한 부여 등의 인증/인가 작업을 수행할 수 있다.
인증/인가에 활용되는 JWT이 탈취된다면, 탈취된 사용자의 개인정보를 조회하거나, 인가되지 않은 범위의 접근 등에 악용될 수 있어 보안에 중대한 위험을 끼치게 된다.
주요 탈취 경로는 대표적으로 XSS 공격
과 CSRF 공격
이 있다.
예시 :
게시글 내용에 script 태그를 입력하여, 게시글을 조회 시 허용되지 않은 스크립트를 실행하는 행위.
→ 주로 백엔드 측에서 게시글 정보를 데이터 베이스에 저장할 때 적절히 필터를 하지 않을 시 XSS 공격이 발생.
예시 :
https://compy.life/logout
으로 GET 요청을 보내었을 때
계정을 로그아웃 처리한다면, 아래와 같이 img 태그로 사용자의 브라우저에 노출만 된다면?
<img src="https://compy.life/logout">
사용자가 의도하지 않았지만, 사용자의 계정은 로그아웃 될 것이다.
이외에도 피싱 사이트를 통해 form 태그의 method 속성을 POST로 설정하여 특정 웹사이트로 POST를 보내어준다면?
저장 위치는 크게 비공개 변수, 로컬 스토리지, 세션 스토리지, 쿠키로 나뉘어진다.
다른 방식에 비해 보안에서 가장 안전하지만 페이지를 이동하거나, 새로고침만 하여도 토큰 정보가 휘발되어
사용자 경험에 좋지 않아 사실상 단독적으로 사용이 불가능하다.
페이지를 새로고침하거나, 이동하여도 토큰이 유지되지만
새로운 탭에서 접속 시 세션이 나뉘어지고, 브라우저가 종료되는 순간 휘발되어 세션 스토리지도 사용자 경험에 좋지 않다.
세션 스토리지는 모든 자바스크립트 코드를 통해 액세스 할 수 있음으로 XSS 공격에도 취약하나
자바스크립트 코드로 제어가 필요하기에 CSRF 공격에서는 안전하다.
로컬 스토리지는 페이지를 이동하거나, 브라우저를 다시 시작하여도 만료 없이 유지된다.
하지만, 세션 스토리지와 동일하게 모든 자바스크립트 코드를 통해 액세스 할 수 있음으로 XSS 공격에 취약하고 CSRF 공격에 안전하다.
옵션 없이 기본적으로 작동되는 쿠키는 사실 XSS, CSRF 공격에 모두 취약하다!
하지만, 백엔드와의 협업을 통해 쿠키에 httpOnly
/ secure
/ SameSite
옵션을 사용한다면
쿠키는 자바스크립트 코드 상에서 접근이 불가능해지고, HTTP 요청에만 포함되어 보내진다.
→ httpOnly
와 secure
, SameSite
등의 옵션은 백엔드 측에서 설정이 필요하며, 브라우저와 통신 시 아래와 같이 서버 측 응답 헤더를 통해 지정된다.
Set-Cookie: 쿠키명=쿠키값; path=/; secure; SameSite=Lax
결국 안전한 JWT 저장을 위해서는 백엔드와 프론트엔드의 협업이 필요하고, 서로 간의 이해가 필요하다.
httpOnly
→ 스크립트 상에서 접근이 불가능하도록 한다.secure
→ 패킷 감청을 막기 위해 https 통신 시에만 해당 쿠키를 사용하도록 한다.SameSite
→ Strict
, Lax
모드가 있으며 Strict
모드에서는 같은 도메인 범위에서만 해당 쿠키를 사용하게 하며, Lax
는 사용자가 페이지 이동 시 혹은 Form을 통한 Get 요청 시에만 허용된다.access token
, refresh token
을 받아온다.access token
은 메모리(변수)에 저장한다.refresh token
은 쿠키에 저장하여 httpOnly
/ secure
/ SameSite
(Strict or Lax 모드) 옵션을 지정한다. (백엔드)Authorization
헤더에 access token
을 보내준다.access token
이 만료되었거나, 페이지 이동으로 사라졌을 시, 서버 렌더링 과정 혹은 API 통신을 통해 재발급을 요청한다.httpOnly
옵션) refresh token
이 이미 담겨진 상태로 서버와 통신하게 된다.refresh token
이 만료되었을 때 DB와 다시 한번 통신하여 갱신 혹은 로그아웃 상태로 렌더링을 하여준다.refresh token
이 저장된 쿠키는 외부 경로와 자바스크립트 상에서의 접근이 불가능하여 CSRF, XSS 공격에서 모두 안전성이 확보된다.access token
이 저장된 비공개 변수는 XSS
, CSRF
공격을 시도할 방법이 사라지며, 토큰이 휘발되어 사라졌던 UX 문제도 해결된다.틀린 내용, 피드백이 있으시다면 댓글 남겨주시면 감사하겠습니다! 🙇♂️
훌륭한 방식이군요!