서버와 클라이언트 간 쿠키 주고받기

HKLeeeee·2023년 11월 23일
0

problem

목록 보기
1/2
post-thumbnail

로그인 기능을 개발하던 중 포트가 다른 두 서버를 띄워 테스트를 해보려했다. 그때 서로 쿠키가 전송되지 않는 문제를 발견했다!

3000번 포트에 접속한 위치에는 쿠키가 있는데

4000번 포트로 돌고있는 서버에는 쿠키가 전송되지 않았다.

console.log로 쿠키를 출력해보았을 때 object null prototype이 출력된 것을 통해 확인해보았다.

이 때 쿠키 설정은 httpOnly이외에 모두 default였다.

왜 보내지지 않았을까?

  1. 도메인이 달라서?

    sameOrigin 정책과 쿠키에 사용되는 sameSite 정책은 다르다.

    GPT한테 두 정책의 차이점을 물어봤다

    SameSite:

    SameSite는 쿠키의 속성 중 하나로, 웹 브라우저가 어떤 상황에서 쿠키를 전송할 것인지를 제어하는 역할을 합니다.

    • SameSite=None: 이 옵션은 모든 상황에서 쿠키가 전송되도록 허용합니다. 이때는 Secure 속성도 함께 설정되어야 하며, HTTPS 연결을 사용하는 경우에만 적용 가능합니다.
    • SameSite=Lax: 기본값이며, 타 사이트로의 요청에서 쿠키를 전송하지 않습니다. 하지만, <a> 태그를 클릭하여 타 사이트로 이동하는 경우에는 쿠키가 전송됩니다.
    • SameSite=Strict: 모든 상황에서 쿠키를 전송하지 않습니다. 타 사이트로의 요청에 대해서도 쿠키가 전송되지 않습니다.

    SameOrigin:

    SameOrigin은 웹 보안 정책 중 하나로, 동일한 출처에서만 리소스를 요청할 수 있도록 하는 규칙입니다.

    • Same-Origin Policy: 이 정책은 기본적으로 다른 출처(도메인, 포트, 프로토콜)에서의 리소스 요청을 차단합니다. 이는 웹 애플리케이션이 특정 출처의 스크립트나 데이터를 불러오는 것을 막아서 보안을 강화합니다.
    • Cross-Origin Resource Sharing (CORS): Same-Origin Policy를 우회하기 위해 사용되는 메커니즘이며, 서버에서 특정 출처로의 요청을 허용하도록 설정하는 것입니다.

    요약하면, SameSite는 쿠키의 전송을 제어하고, SameOrigin은 웹 리소스의 출처에 대한 보안을 강화하는 정책입니다. 두 가지 개념은 서로 다른 측면에서 웹 보안을 다루고 있습니다.

    Samesite는 하위 도메인까지도 Samesite로 간주한다.

    우리의 도메인으로 예를 들면 algoitni.site와 api.algoitni.site는 SameSite로 쿠키 전송이 가능하다.

    로컬에서 테스트하는 경우는 도메인이 같으므로 이 문제는 아니다.

  2. Cookie 설정할 때 samesite 옵션을 지정해주지 않으면 default를 Lax로 동작한다.

    setCookie의 samesite 옵션에는 none, Lax, strict가 있다. 위에 GPT가 잘 설명해줬다.

    현재 상태는 Lax이다. a 태그로 변경해주니 서버에서 쿠키 정보를 받을 수 있었다.


button은 작동하지 않지만


a 태그로 보냈을 때 쿠키 정보가 서버에 잘 전송되어 출력되었다.

그래도 이상하다.
localhost는 samesite인데 Lax에 막히다니?
button 태그에 fetch로 요청을 보내고 있어서 fetch가 의심스러웠다.

  1. fetch?!?!

    아래와 같이 요청을 보내고 있었다.

    <button type="button" id="info">유저 정보 조회</button>
    <script>
        document.getElementById("info").addEventListener("click", ()=>{
            fetch("http://localhost:4000/auth/profile")
            .then(res =>  res.json())
            .then(console.log)
        })
    </script>

    fetch() 전역 함수 - Web API | MDN

    fetch 요청시 브라우저가 쿠키, 인증서등을 보낼지 credential 옵션으로 설정해줄 수 있는데,

    알고보니 fetch 요청 credential 옵션의 기본값이 “same-origin”이었다.

    로컬 테스트 시 쿠키의 same site 정책에는 위배되지 않지만 fetch 요청의 same-origin 정책에 위배되어 값을 받을 수 없었던 것이다.

fetch 요청의 옵션을 변경해주고 나니 로컬에서 테스트에 성공했다.

document.getElementById("info").addEventListener("click", ()=>{
    fetch("http://localhost:4000/auth/profile", {credentials: 'include'})
   .then(res =>  res.json())
   .then(console.log)
 })


전 부터 쿠키옵션을 하나씩 적용해보고 있었는데 SameSite로 엄청 삽질한 기념으로 쿠키옵션을 정리해봤다.

쿠키 옵션

Http Only

https only 옵션을 true로 주면 자바스크립트로 조회할 수 없다.

이 옵션을 주면 XSS 공격을 예방할 수 있다.

XSS(Cross-Site Scripting)
악의적인 용도로 웹에 스크립트를 삽입하는 공격.

Http Secure

Http Secure 옵션을 true로 주면 Https 통신환경에서만 쿠키가 전송된다.

로컬호스트에서는 예외라고 한다.

SameSite

같은 Site에서만 쿠키를 이용할지 설정해주며 옵션은 세 가지가 있다.

SameSite 옵션을 통해서 다른 사이트에 우리서버의 쿠키값을 전달하는 것을 방지해 CSRF 공격을 예방할 수 있다.

CSRF (Cross Site Request Forgery)
사용자가 자신의 의지와는 무관하게 공격자가 의도한 행위(수정, 삭제, 등록 등)를 특정 웹사이트에 요청하게 하는 공격

SameSites는 도메인과는 약간 다른 개념인데, 하위 도메인이 같은 경우에도 같은 site로 인정한다.

예를 들면 algoitni.site와 api.algoitni.site는 SameSite 이다.

  • None Site를 구분하지 않고 항상 쿠키를 같이 보낸다. 이 옵션을 사용하려면 Http Secure가 ture가 되어있어야한다.
  • Lax 별다른 옵션이 없으면 Lax 옵션으로 작동한다. 안전하다고 판단되는 예외에는 쿠키를 보내고, 그 이외의 경우에는 같은 Site에만 쿠키를 보낸다. 예외에는 a태크의 href속성으로 보내는 것, 같은 site 간의 GET 메서드 등이 있다.
  • Strict 같은 Site에만 쿠키를 보낸다.

Max-Age, Expires

쿠키의 유효기간을 설정한다.

express에서는 별도로 설정하지 않으면 session으로 설정된다.

유효기간이 세션인 쿠키는 브라우저가 닫히면 삭제된다.

Expires 옵션은 유효기간을 타임스탬프로 지정해주어야하며

Max-Age 옵션은 초로 유효기간을 지정해준다.

Path

도메인에서 쿠키가 적용될 경로를 지정한다.

만약 쿠키 Path가 /user 인 경우 /post 경로에서는 쿠키를 이용할 수 없다.

express의 기본값은 root(’/’)로 root Path가 적용되면 해당 사이트 모든 경로에서 그 쿠키를 사용할 수 있다.

express의 response.cookie 를 통해서 생성하지 않고 Set-Cookie 헤더로 직접 쿠키를 적용할 때 Path 옵션이 주어져 있지 않으면 그 요청이 들어온 위치로 지정되었다.

profile
야생의 개발자!

0개의 댓글

관련 채용 정보