
Express로 Restful API 개발 실습을 진행하며 JWT 인증 프로세스를 설계하고 JWT 저장 방법에 대해 고민하며 공부한 내용을 정리해보았다
설계한 JWT 인증 프로세스는 다음과 같습니다

사용자가 서버에 로그인 요청을 보낸다
인증 절차를 거친 후 인증이 유효하면 서버에서 암호화된 JWT의 Access Token 과 Refresh Token 를 발급한다
발급한 토큰을 헤더에 담아 사용자에게 전달한다
사용자는 토큰을 저장하고 추후 서버에 재요청시 발급받은 Access Token 을 서버에 전달하고 서버는 이를 검증하고 응답한다
만약 Access Token 이 만료되었다면 사용자는 Refresh Token를 사용해 새로운 Access Token 을 발급받는다
서버는 Refresh Token 과 DB에 저장된 Refresh Token 을 비교하여 유효하다고 판단하면 새 Access Token 을 발급하여 사용자에게 전달한다
Access Token 은 접근에 관여하는 토큰이다
토큰의 유효기간이 짧다
평소 API 통신할 때 활용한다
Refresh Token 은 토큰의 재발급에 관여하는 토큰이다
토큰의 유효기간이 길다
탈취 위험이 큰 Access Token의 만료 기간을 짧게 두고 Refresh Token을 발급하여 탈취의 위험을 최소화한다
로그인 이후 사용자는 서버에 추후 요청을 위해 토큰을 함께 전달해야한다
따라서 사용자는 토큰을 별도로 저장하고 있어야한다
이때 토큰을 저장하는 방식은 크게 두 가지로 구분된다
LocalStorge 에 저장하는 방식과 Cookie 에 저장하는 방식이다
장점
사용자 측에서 데이터를 저장하므로 서버에 추가적인 요청이 필요없다
쿠키보다 네트워크 트래픽을 줄일 수 있다
단점
사용자 측에서 js로 저장 데이터를 읽을 수 있어서 XSS 공격에 취약하다
장점
HttpOnly와 Secure 속성을 설정하여 JavaScript 코드에서 쿠키에 접근할 수 없도록 설정할 수 있다 즉 XSS 방어 가능하다
단점
CSRF 공격에 취약하다

XSS 공격 기법은 악의적인 스크립트를 입력하여 사용자가 이 스크립트를 읽게 유도한 다음 쿠키나 세션 토큰 등의 중요 정보를 빼오는 공격 기법이다
예를 들면 사용자가 클릭할 수 있는 게시글이나 댓글에 스크립트를 삽입하고 해당 페이지에 접속하면 정보를 탈취하는 방식이다

쿠키는 브라우저가 요청할 때마다 함께 전송되므로 악의적인 웹 사이트에서는 사용자의 인증 정보가 포함된 쿠키를 사용하여 서버에 요청을 보낼 수 있습니다
즉 사용자의 의지와 관계 없이 악의적인 행동을 공격자가 요청할 수 있다
예를 들어 사용자가 은행 웹 사이트에 로그인한 상태에서 악의적인 웹 사이트를 방문하는 경우, 이 사이트는 자동으로 은행 웹 사이트로 이체 요청을 보낼 수 있다
결론부터 말하자면 대부분의 사람들은 Cookie 저장 방식을 선택한다
두 저장 방식 모두 문제점이 존재하는데 왜 Cookie에 저장하는 방식이 유리할까??
HttpOnly 설정을 통해 Javascript가 해당 쿠키로 접근하는 것을 차단할 수 있어 XSS 공격에 대한 위험이 감소한다
Secure 설정을 통해 쿠키는 HTTPS 프로토콜을 통해서만 전송되기 때문에 중간자의 공격으로부터 안전하다
쿠키에서 취약한 CSRF 공격은 다음 방법들을 통해 방어가 가능하다
3.1 CSRF 토큰 사용
임의의 난수로 구성된 CSRF 토큰을 서버 메모리에 생성하고 이를 중요한 요청의 매개변수로 포함시킨다
사용자가 중요 요청을 보낼 때 CSRF 토큰을 함께 전송하여 검증을 하게 되며 유효하지 않은 경우 요청을 실행하지 않는다
3.2 SameSite 속성 설정
SameSite 속성을 Strict로 설정하여 쿠키가 원본 사이트에서만 전송되도록 설정한다
Cookie를 전달할 때 현재 페이지 도메인과 요청받는 도메인 값이 같아야한 요청을 실행하므로 공격 방어가 가능하다
로그인은 개인 정보를 담고 있는 중요한 정보이기 때문에 안전한 로그인 방식에 대해 다시 생각해볼 수 있었고 이를 적용하여 추가적인 구현을 하도록 공부할 예정이다
지금 사용하는 velog 도 JWT 인증 방식을 활용하고 있음을 확인해보았다

