WEB 슬랙 프로젝트를 진행하던중 로그인 기능을 위해 발급한 JWT를 어디에 저장하는지가 고민의 시작이었다.
아래의 고민들은 대체로 사용의 편의성 및 서버 리소스 최소화를 위해 클라이언트에 저장을 하는것을 전제로 생각하였다.
local storage에 저장하면 보안상 문제가 된다. (XSS)
httponly, secure 옵션을 사용하여 cookie에 저장하면 local storage보다는 안전하다.
workspaceUserInfo의 id가 사실상 user의 id처럼 사용되기 때문에 jwt로 관리하는게 맞는 것 같다.
userId와 workspaceUserInfoId를 같이 jwt 토큰을 생성해야할까 따로 생성해야 할까? -> 같이 하나로 생성하자.
실제 서비스되고 있는 web slack은 localstorage에 채널 정보와 같이 잘 변하지 않는 데이터들을 저장하여 사용하고 있다.
현재 우리가 고민하는 문제는 유저 정보를 어떻게, 어디에 저장하는지가 문제가 되고 있기 때문에 참고 사항이 될 수 없었다.
분명 어딘가에 로그인 유무를 확인 할 수 있는 데이터를 저장 할텐데 파악하지는 못하였다.
singed cookie: 쿠키 암호화 옵션
httponly: http 통신을 통해서만 쿠키를 제어하도록 하는 옵션
secure: https 환경에서만 쿠키를 사용하도록 강제하는 옵션
위의 옵션들을 활용하면 취약점을 보완할 수 있다.
현재는 jwt를 쿠키에 저장하는 방법을 사용하고 있으며 저장할 때 여러 옵션을 적용하기로 하였다.
우선 signed cookie를 사용하며 https를 이용할 때 사용할 수 있는 secure 옵션을 적용하였다.
또한 프론트 페이지를 제공해주는 웹서버와 API서버가 분리되어 있어 다른 도메인일 경우 쿠키를 저장하지 않도록 하는 보안 정책이 적용되었다.(CSRF 방지)
SameSite 속성을 변경해주면 보안 정책을 회피하여 쿠키를 저장할 수 있다. (보안적으로는 좋지 못하기 때문에 추후 다른 방법을 알아볼 예정)
최종적으로 설정한 쿠키의 옵션은 다음과 같다.
현재 refresh token 없이 오로지 access token을 쿠키에 저장하여 사용하고 있기에 1시간마다 주기적으로 사용자 로그인을 다시 해줘야하는 문제점이 있다.
잦은 로그인을 막기 위해 refresh token을 저장하도록하고 access token은 refresh token을 통해 주기적으로 자동 발급 되도록 개선 하면 될것 같다.
좀 더 좋은 보안을 위해서는 JWT만을 보관하는 DB를 사용하고 해당 DB에 저장된 id값을 쿠키에 보관하여 refresh token으로 accss token을 발급 받을 때만 DB에 저장된 JWT를 확인하여 access token을 발급받으면 좋지 않을까 싶다.
access token은 탈취당하는것을 염려하여 유효기간을 주로 1시간으로 설정하기 때문에 쿠키에 저장하더라도 문제가 적을것이다.