CSRF(Cross Site Request Forgery)
CSRF는 다른 사이트(Cross Site)에서 유저가 보내는 요청(Request)를 조작(Forgery)하는 것입니다.
예를 들어, 이메일을 받았는데, 그 이메일에 첨부된 링크를 눌렀습니다. 그 링크를 누르면, 그 링크가 은행 계좌로 요청을 보내어 의도하지 않은 돈이 출금되는 그런 사례입니다.
이런 공격이 생기게 된 이유는, 해커가 직접 데이터를 접근할 수 없기 때문입니다. 직접 데이터에 접근할 수 있었다면 굳이 나에게 링크를 보낼 필요가 없기 때문입니다.
해커가 직접 데이터에 접근할 수 없는 이유는 다른 사이트이기 때문에 Response에 직접 접근할 수 없는 것입니다.
CSRF 공격을 위한 조건은 아래와 같습니다.
쿠키를 사용한 로그인
예측할 수 있는 요청/Parameter를 가지고 있어야 합니다.
CSRF를 막는 방법
CSRF 토큰 사용하기
Same-Site cookie 사용하기
토큰 기반 인증을 사용하는 이유
세션 기반 인증 방식은 서버 또는 DB에 유저 정보를 담는 방식입니다. 서버에서는 민감하거나 제한된 정보를 요청할 때마다 유저에게 정보를 줘도 괜찮은지 확인합니다. 매번 요청할 때마다 위 작업을 수행합니다.
이런 반복 작업은 서버 또는 DB에 부담을 주게 됩니다. 그래서 클라이언트에게 이 부담을 넘기기 위해 고안되었습니다.
Token은 클라이언트가 갖고있고, 클라이언트가 서버에게 토큰을 보여주는 것으로 일종의 놀이공원 입장 티켓과 유사합니다.
토큰은 유저 정보를 암호화한 상태로 담을 수 있고, 암호화했기 때문에 클라이언트에 담아도 문제가 없습니다. 토큰 저장 방식으로는 JWT를 널리 사용하고 있습니다.
JWT(Json Web Token)은 Json 포맷으로 사용자에 대한 속성을 저장하는 웹 토큰 입니다.
JWT의 구조는 아래와 같습니다.
aaaaaa.bbbbbb.cccccc
세 덩어리로 나눌 수 있는데, 각 덩어리는 앞에서부터 Header, Payload, Signature입니다.
{"alg":"HS256", "typ":"JWT"}
{"sub":"sominformation","name":"john","iat":151623391}
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
Access Token은 유저의 이메일, 연락처, 사진 등 보호된 정보들에 접근 가능한 권한 부여에 사용됩니다. 클라이언트가 로그인할 때, 위 두가지 토큰을 모두 부여받지만 실제로 권한을 얻는 데 사용하는 토큰은 Access Token입니다.
이 Access Token이 타인이 얻게됐을 때, 부여받은 권한으로 악의적인 요청을 서버에 보낼 수 있습니다. 이를 방지하기 위해 이 토큰엔 짧은 유효기간을 할당해 탈취되더라도 사용하기 어렵게끔 해야합니다.
이 토큰의 유효기간이 만료된다면 Refresh Token으로 새로운 Access Token을 발급받습니다.
클라이언트가 서버에 아이디와 비밀번호를 담아 로그인 요청을 보냅니다.
서버는 아이디와 비밀번호가 일치하는지 확인하고, 클라이언트에게 보낼 JWT 토큰(Access, Refresh)을 생성합니다.
JWT를 클라이언트에게 보내고, 클라이언트는 이 토큰을 저장합니다.
클라이언트는 LocalStorage나 쿠키, 리액트의 State등 다양한 공간에 저장할 수 있습니다.
클라이언트가 HTTP 헤더에 토큰을 담아 서버에게 GET 요청을 합니다.
서버는 JWT 토큰을 해독하고, 발급해준 토큰이 맞는지 판단이 된다면 그에 따른 응답을 보냅니다.
서버는 클라이언트에 대한 정보를 저장할 필요가 없습니다. 토큰 해독이 되는지만 판단하면 됩니다. 서버와 DB에 부담을 덜게 됩니다.
클라이언트는 새로운 요청을 보낼 때마다 토큰을 헤더에 포함하면 됩니다.
서버가 나뉘어있다면, 하나의 토큰만으로 여러 서버에서 인증을 받을 수 있습니다.
암호화된 키와 토큰을 노출할 필요가 없기 때문에 안전합니다.
토큰을 확인하는 서버가 꼭 토큰을 만들지 않아도 됩니다. 토큰만 생성하는 서버를 만들거나, 다른 회사에서 토큰 관련 작업을 맡길 수 있습니다.
토큰의 내용물 안에 어떤 정보에 접근 가능한지 정해줄 수 있습니다. 예를 들어, 서비스의 사진과 연락처 사용 권한을 부여하는 방법, 사진만 부여하는 방법 등입니다.