Aling 프로젝트 진행 중 AccessToken과 RefreshToken을 어디에 저장해야 하는지에 고민했던 내용을 정리해보았다.
XSS(Cross Site Scripting), CSRF(Cross Site Request Forgery)
Web Storage - Local Storage
무엇인가?

: 도메인 별로 로컬 데이터를 저장할 수 있도록 지원하는 저장소를 말한다. HTML5에 추가되었으며, key-value 형태지만 문자열 데이터만 지원하고 만료기간이 존재하지 않는다. (영구저장==컴퓨터를 끄고 켜도 유지된다) 웹 스토리지 중 세션 스토리지는 브라우저를 닫으면 소멸되기 때문에 고려하지 않았다.
👍 CSRF 위조로 인한 요청의 경우, 사용자의 브라우저에 있는 쿠키가 서버로 전달되기 때문에 Cookie에 토큰을 담는 경우 모든 요청이 수락될 수 있다. 하지만 Local Storage에 넣는다면 요청에 토큰이 담긴 쿠키가 함께 전달되지 않기 때문에 인증된 요청으로 쓰이지 않는다.
👎 But, 로컬 스토리지는 XSS에 취약하다. JS 코드를 실행시켜 로컬 스토리지에 있는 토큰을 얻어낼 수 있다.
Cookie
무엇인가?

: http 프로토콜은 stateless하다. 서버는 브라우저를 통해 클라이언트측에 어떠한 정보를 남겨 놓는데, 이 때 그 임의의 데이터 조각을 쿠키라고 한다. key-value 형태이며 만료기간이 존재한다.
👍 httpOnly 옵션을 달아 XSS를 막을 수 있다. 하지만 httpOnly는 JS 코드로 얻어낼 수 없을 뿐, 요청을 보낸다면 쿠키가 서버측으로 전달되기 때문에 완전하게 안전한 것은 아니다. 때문에 요청 도메인과 쿠키에 설정된 도메인이 같은 경우에만 쿠키를 싣도록 하는 SameSite 옵션도 존재한다.
👎 But, Cookie 자체로 들어오는 것을 막을 순 없기 때문에 CSRF의 위조된 요청로 인한 공격은 막을 수 없다.
Access Token과 Refresh Token 모두 다 쿠키로 저장하는 방법
이유 : 쿠키 옵션을 달아 XSS를 막을 수 있고, CSRF 요청도 다른 방어기법 ex. referer(어떤 경로로 왔니?) 등을 사용해 대처할 수 있다.
결론 : CSRF를 잘 막아내고 쿠키로 통일한다.
Access Token은 로컬 스토리지로, Refresh Token은 쿠키로 저장하는 방법
이유 : Access Token은 30분으로 짧게 설정해 놓았기 때문에 로컬스토리지에서 만약, 만약! 탈취되어도 유효 30분이고, 쿠키에 Access Token이 담겨있지 않기 때문에 요청에 쿠키가 함께 전달되어도 괜찮다.
결론 : Access Token을 XSS 취약하게 두고 CSRF을 막아낸다.