배경
JWT토큰을 어디에 보관해야 되는지 제대로 알아보고 싶었습니다.
구글에 검색을 했을 때 대부분 LocalStorage에 보관하여 사용하는 글들이 정말 많습니다. 저도 생각없이 똑같이 구현했었습니다. 이러한 방식이 잘못되었다는 것을 깨닫고, 다른 사람들에게 공유하고 싶어서 글을 작성했습니다.
간단한게 LocalStoage가 뭔지 설명하고, 왜 LocalStoarge를 사용하면 안 되는지 설명하겠습니다.
LocalStoarge
로컬스토리지 객체는 웹 스토리지(WebStorage) 중 하나입니다. 로컬스토리지 객체를 통해 브라우저 내에 키-값(key-value) 데이터 쌍을 저장할 수 있습니다.
데이터 공유 여부
데이터를 브라우저에 반영구적으로 저장하며, 브라우저를 종료 후 재시작해도 데이터가 남아있습니다.
또한 다른 창과 브라우저를 통해서도 접근이 가능합니다.
새로운 브라우저, 종료 후 재시작해도 데이터가 남아있음을 확인할 수 있습니다.
LocalStoarge를 사용하지 마라
액세스 토큰 저장
로그인 완료 후, 액세스 토큰을 로컬 스토리지에 저장하는 로직입니다.
if (token) {
localStorage.setItem("access_token", token);
}
왜 사용하면 안 될까?
위에서 확인할 수 있듯이, 로컬스토리지에 저장을 했을 때 localstorage.getItem()을 이용하여 누구나 브라우저에서 로컬스토리지에 있는 데이터를 다 확인할 수 있습니다.
그렇기 때문에 XSS공격에 매우 취약함을 확인할 수 있습니다.
따라서 로컬스토리지에 중요한 정보를 저장하면 악성 스크립트로 사용자의 정보가 탈취될 수 있습니다.
그럼 어디에 저장해야 될까요?
해결 방법은 Cookie에 저장하는 것입니다.
Cookie를 이용하면?
로그인 후 Cookie를 저장하는 로직
ResponseCookie accessToken = ResponseCookie
.from("accessToken", token)
.path("/")
.maxAge(3600)
.sameSite("Lax")
.build();
response.addHeader("Set-Cookie", accessToken.toString());
JWT토큰을 쿠키에 저장하는 로직입니다.
쿠키를 사용하여 XSS공격을 막는 방법을 살펴보겠습니다.
쿠키도 접근이 가능합니다.
근데 왜 쿠키를 이용하라고 했을까요?
쿠키에는 httpOnly 옵션이 존재하기 때문입니다.
httpOnly
쿠키를 저장하는 로직을 다시 보겠습니다.
이번에 httpOnly 옵션을 true로 설정합니다.
ResponseCookie accessToken = ResponseCookie
.from("accessToken", token)
.path("/")
.httpOnly(true)
.maxAge(3600)
.sameSite("Lax")
.build();
response.addHeader("Set-Cookie", accessToken.toString());
옵션을 넣은 후 다시 보겠습니다.
httpOnly 옵션을 사용하면 document.cookie를 이용하여 쿠키 정보를 빼낼 수 없음을 확인할 수 있습니다.
따라서 중요한 정보는 무조건 Cookie를 이용하여 저장해야 합니다!
httpOnly 옵션을 사용한 쿠키는 브라우저에서 document를 이용하여 접근할 수 없고,
HTTP를 통하여 서버에 전송될 때만 확인할 수 있습니다.
마치며
현재 인터넷에 흔히 볼 수 있는 코드는 토큰을 로컬스토리지에 저장하여 사용하는 코드입니다.
XSS공격에 취약한데 왜 로컬스토리지에 저장하여 사용하는지 XSS공격을 직접 구현해보고 로컬스토리지를 이용했을 때, 쿠키를 이용했을 때 어떠한 차이가있는지 학습 후 글을 통해 다른 사람들에게도 알리고 싶었습니다.
이번 게시글을 작성하면서 로컬스토리지, 쿠키, XSS 공격에 대해 더 깊이 학습할 수 있었고
단순하게 기능만 구현하는 것보다 명확한 이유를 기반으로 코드를 짤 수 있었습니다.
앞으로도 이러한 방식으로 꾸준히 나아가겠습니다.
밑에 글은 CSRF 공격에 대한 내용과 직접 구현 그리고 쿠키를 이용하였을 때 CSRF 공격을 방어하는 방법입니다.
https://byungil.tistory.com/324
'Spring' 카테고리의 다른 글
테스트 코드 - Presentation Layer (0) | 2023.11.12 |
---|---|
CSRF(Cross-Site Request Forgery)란? (1) | 2023.10.19 |
XSS(Cross Site Scripting) 공격 (0) | 2023.10.16 |
Redis) 싱글벙글 Refresh Token을 Redis에 저장하고 사용해보자 (0) | 2023.08.04 |
Lombok - 활성화 시키는 방법 (0) | 2023.01.06 |