요즘은 한창 프론트엔드 진행중이다.
로그인 기능을 개발하며 드디어 다시 JWT에 관해 고민하게되었다.
꽤 단골주제이긴한데, 넘겨받은 JWT 토큰을 쿠키에 저장할지, 로컬 스토리지에 저장할지다.
우선, 쿠키와 로컬스토리지 각각의 장단점부터 파악해봤다.
Cookie
- 장점
- 간단한 데이터파일로 서버와 클라이언트가 쉽게 주고받을 수 있다.
- 단점
- 저장용량이 작고, 보안에 취약하다. ( 서버와 통신하며 주고받는 구간에서 탈취의 위험이 존재함 )
Local Storage
- 장점
- 클라이언트측에서 저장만하기때문에 쿠키에비해 보안 이점이있다.
- 브라우저를 종료해도 데이터는 남아있는다. (반영구적)
- 단점
- 모든 브라우저가 지원하지는 않는다. ( Internet Explorer 7 이하 버전은 지원하지않는다.... )
- 클라이언트 즉 브라우저에 값을 반영구적으로 저장하기때문에 사용자가 개인 컴퓨터가 아닌 공공장소의 PC 이용의 경우 보안에 취약할 수 있다.
생각보다 쉽게 결정이 났다.
쿠키는 말그대로 쿠키처럼 가볍게 주고받는 데이터에 적합하다.
예를 들자면, 사용자의 팝업창 종료 정보 ( n일간 다시보지않기 ) , 간단한 결제 정보등 탈취당해도 크게 위험하지않는 데이터를 다룰때 쿠키가 적합하다고 생각하고,
로컬 스토리지의 경우
사용자의 정보가 담겨있는 중요한 데이터를 다룰때에 적합하다고 생각한다.
( 다만, 개인 컴퓨터가 아닐경우에 로그아웃을 해달라는 알림을 알려 스토리지의 데이터를 삭제하자 )
이 후 권한 인증이 필요한 요청의 경우
로컬 스토리지의 저장되어있는 액세스토큰을 localStroage.getItem('accessToken')으로 꺼내 담아 요청하면 완료.
(액세스토큰이 만료되면 리프레쉬토큰을 보낸 뒤 갓만든 따끈따끈한 액세스토큰으로 재요청을 진행하자)
라고... 도장을 찍었지만 친구에게 지적을 받고 다시 개발에 들어갔다.
LocalStorage에 AccessToken, RefreshToken 모두를 한꺼번에 저장하는게 맞는지에 대해 다시 고민해보라고 피드백을 받았다.
생각해보니 만약에 한곳에 모두 저장시 XSS공격으로 LocalStrorage가 노출된다면 두 개의 토큰 모두를 탈취당하는 상황이 온다.
옛말에 계란은 한바구니에 담지말라 라는 말처럼 소중한 JWT Token 역시 한바구니에 담지말자...
그럼 각각의 토큰을 어디에 담을지에 대해 고민해보자.
LocalStroage는 용량이 크고 반영구적이다.
AccessToken은 만료시간이 매우 짧으며 (3분으로 설정해놨다.) RefreshToken에 비해 담겨진 정보가 많으므로
AccessToken은 LocalStorage에 담기로 결정,
그리고 현재 리액트에서 LocalStorage에 담겨있는 AccessToken의 정보로 로그인 유무를 판단하므로
JavaScript로 AccessToken에 접근 할 수 있어야한다.
Cookie는 가볍고 axios에서 withCredential 설정시 간편하게 서버와 쿠키를 주고받을 수 있다.
이 점에서 따로 자바스크립트 코드를 작성하지 않아도 쉽게 RefreshToken을 넘겨줄 수 있겠다 싶어 RefreshToken은 Cookie로 결정
다만 보안을 위해 서버에서 httpOnly, secure 설정을 true로 해줬다. (Javascript 로 조작해 탈취하지 못하도록 )
AccessToken과 RefreshToken의 저장을 분리했으므로 Client에서 로그아웃도 변경이 됬다.
기존에는 localstorage에 있는 모든 토큰을 삭제하기만 하면 됬지만,
쿠키에 존재하는 RefreshToken을 따로 삭제해야됬다.
HttpOnly설정으로 JavaScript에서 Cookie에 접근할 수 없다. 즉, 리액트에서 쿠키를 삭제 할 수 없기때문에
Spring에서 쿠키를 따로 삭제해주기로 했다.
React에서는 Cookie에 접근할 수 없지만 Axios의 withCredentials 설정을 할 경우 쿠키를 서버에 보낼 수 있게된다.
요청으로 받은 쿠키를 서버에서 만료시간을 0으로준 뒤 삭제에 성공
'Project > TomorrowLand' 카테고리의 다른 글
화면상에서 권한별 동적 렌더링에대한 고민 (0) | 2024.02.14 |
---|---|
Axios를 이용해 BinaryFile Upload 하기 (0) | 2024.01.30 |
Image Upload, MIME Type을 Octet-Stream으로 결정한 이유 (0) | 2024.01.11 |
Testable Code 작성을 위한 노력 1 (0) | 2024.01.11 |
테스트 케이스를 작성하지말자. (0) | 2024.01.11 |