SameSite 쿠키 레시피

Chrome, Firefox, Edge 등은 IETF 제안서인 점진적으로 개선된 쿠키에 따라 기본 동작을 변경하여 다음과 같은 이점을 제공합니다.

  • SameSite 속성이 없는 쿠키는 SameSite=Lax로 간주되므로 기본 동작은 쿠키를 퍼스트 파티 컨텍스트로 제한하는 것입니다.
  • 교차 사이트 사용을 위한 쿠키는 서드 파티 컨텍스트에 포함되도록 SameSite=None; Secure를 지정해야 합니다.

아직 업데이트하지 않았다면 향후 서드 파티 쿠키가 차단되지 않도록 서드 파티 쿠키의 속성을 업데이트해야 합니다.

브라우저 지원

  • Chrome: 51
  • Edge: 16.
  • Firefox: 60
  • Safari: 13

소스

교차 사이트 또는 서드 파티 쿠키 사용 사례

서드 파티 컨텍스트에서 쿠키를 전송해야 하는 여러 일반적인 사용 사례와 패턴이 있습니다. 이러한 사용 사례 중 하나를 제공하거나 이에 종속되는 경우 서비스가 올바르게 작동하도록 개발자 또는 제공업체가 쿠키를 업데이트해야 합니다.

<iframe> 내 콘텐츠

<iframe>에 표시되는 다른 사이트의 콘텐츠는 서드 파티 컨텍스트에 있습니다. 표준 사용 사례는 다음과 같습니다.

  • 동영상, 지도, 코드 샘플, 소셜 게시물 등 다른 사이트에서 공유된 삽입된 콘텐츠
  • 결제, 캘린더, 예약, 예약 기능과 같은 외부 서비스의 위젯
  • 소셜 버튼이나 사기 방지 서비스와 같이 <iframes>가 눈에 띄지 않게 만드는 위젯

여기에서는 세션 상태를 유지하거나, 일반 환경설정을 저장하거나, 통계를 사용 설정하거나, 기존 계정이 있는 사용자를 위해 콘텐츠를 맞춤설정하는 등 다양한 목적으로 쿠키를 사용할 수 있습니다.

삽입된 콘텐츠의 URL이 페이지의 URL과 일치하지 않는 브라우저 창의 다이어그램
삽입된 콘텐츠가 최상위 검색 컨텍스트와 동일한 사이트에서 가져온 것이 아니라면 서드 파티 콘텐츠입니다.

웹은 본질적으로 컴포저블이므로 <iframes>는 최상위 또는 퍼스트 파티 컨텍스트에서 조회된 콘텐츠를 삽입하는 데도 사용됩니다. iframe에 표시된 사이트에서 사용하는 모든 쿠키는 서드 파티 쿠키로 간주됩니다. 다른 사이트에서 삽입할 사이트를 만들고 사이트가 작동하려면 쿠키가 필요한 경우 쿠키가 크로스 사이트 사용에 대해 표시되어 있는지 또는 쿠키 없이도 원활하게 대체할 수 있는지 확인해야 합니다.

여러 사이트에서 '안전하지 않은' 요청

'안전하지 않음'이 여기에서 우려되는 것처럼 들릴 수 있지만 상태를 변경하려는 의도가 있을 수 있는 모든 요청을 의미합니다. 웹에서는 주로 POST 요청입니다. SameSite=Lax로 표시된 쿠키는 링크를 클릭하여 다른 사이트로 이동하는 것과 같이 안전한 최상위 탐색에서 전송됩니다. 하지만 POST를 사용하여 다른 사이트에 제출하는 <form>와 같은 경우에는 쿠키가 포함되지 않습니다.

한 페이지에서 다른 페이지로 이동하는 요청의 다이어그램
수신 요청이 '안전' 메서드를 사용하는 경우 페이지에서 쿠키를 전송합니다.

이 패턴은 사용자를 원격 서비스로 리디렉션하여 일부 작업을 실행한 후 다시 돌아올 수 있는 사이트(예: 서드 파티 ID 공급자로 리디렉션)에 사용됩니다. 사용자가 사이트를 나가기 전에 일회용 토큰이 포함된 쿠키가 설정되며, 이 토큰은 반환 요청에서 확인하여 크로스 사이트 요청 위조 (CSRF) 공격을 완화할 수 있습니다. 반환 요청이 POST를 통해 전송되는 경우 쿠키를 SameSite=None; Secure로 표시해야 합니다.

원격 리소스

<img> 태그 또는 <script> 태그와 같이 페이지의 모든 원격 리소스는 요청과 함께 전송되는 쿠키를 사용할 수 있습니다. 일반적인 사용 사례로는 추적 픽셀과 콘텐츠 맞춤설정이 있습니다.

이는 fetch 또는 XMLHttpRequest를 사용하여 JavaScript에서 전송된 요청에도 적용됩니다. fetch()credentials: 'include' 옵션으로 호출되면 이러한 요청에 쿠키가 포함될 가능성이 높습니다. XMLHttpRequest의 경우 예상 쿠키는 일반적으로 truewithCredentials으로 표시됩니다. 이러한 쿠키는 크로스 사이트 요청에 포함되도록 적절하게 표시되어야 합니다.

WebView 내 콘텐츠

플랫폼별 앱의 WebView는 브라우저를 기반으로 합니다. 개발자는 앱에 영향을 미치는 제한사항 또는 문제가 앱의 WebView에도 적용되는지 테스트해야 합니다.

또한 Android에서는 플랫폼별 앱이 CookieManager API를 사용하여 쿠키를 직접 설정할 수 있습니다. 헤더 또는 JavaScript를 사용하여 설정된 쿠키와 마찬가지로 교차 사이트 사용을 목적으로 하는 경우 SameSite=None; Secure를 포함하는 것이 좋습니다.

지금 SameSite를 구현하는 방법

퍼스트 파티 컨텍스트에서만 필요한 쿠키는 필요에 따라 SameSite=Lax 또는 SameSite=Strict로 표시합니다. 이러한 쿠키를 표시하지 않고 대신 기본 브라우저 동작을 사용하여 처리하면 브라우저 간에 일관되지 않게 동작할 수 있으며 각 쿠키에 대한 콘솔 경고가 트리거될 수 있습니다.

Set-Cookie: first_party_var=value; SameSite=Lax

서드 파티 컨텍스트에 필요한 쿠키는 모두 SameSite=None; Secure로 표시해야 합니다. 두 속성 모두 필수입니다. Secure 없이 None만 지정하면 쿠키가 거부됩니다. 브라우저 구현의 차이를 고려하려면 호환되지 않는 클라이언트 처리에 설명된 완화 전략 중 일부를 사용해야 할 수 있습니다.

Set-Cookie: third_party_var=value; SameSite=None; Secure

호환되지 않는 클라이언트 처리

None를 포함하고 기본 동작을 업데이트하는 이러한 변경사항은 아직 비교적 새롭기 때문에 브라우저마다 다르게 처리합니다. 알려진 문제 목록은 chromium.org의 업데이트 페이지를 참고하세요. 이 목록은 완전하지 않을 수 있습니다.

한 가지 해결 방법은 각 쿠키를 새 스타일과 이전 스타일로 모두 설정하는 것입니다.

Set-cookie: 3pcookie=value; SameSite=None; Secure
Set-cookie: 3pcookie-legacy=value; Secure

최신 동작을 구현하는 브라우저는 SameSite 값으로 쿠키를 설정합니다. 새 동작을 구현하지 않는 브라우저는 이 값을 무시하고 3pcookie-legacy 쿠키를 설정합니다. 포함된 쿠키를 처리할 때 사이트는 먼저 새 스타일의 쿠키가 있는지 확인한 다음 새 쿠키를 찾을 수 없는 경우 기존 쿠키로 대체해야 합니다.

다음 예에서는 Node.js에서 Express 프레임워크cookie-parser 미들웨어를 사용하여 이 작업을 수행하는 방법을 보여줍니다.

const express = require('express');
const cp = require('cookie-parser');
const app = express();
app.use(cp());

app.get('/set', (req, res) => {
  // Set the new style cookie
  res.cookie('3pcookie', 'value', { sameSite: 'none', secure: true });
  // And set the same value in the legacy cookie
  res.cookie('3pcookie-legacy', 'value', { secure: true });
  res.end();
});

app.get('/', (req, res) => {
  let cookieVal = null;

  if (req.cookies['3pcookie']) {
    // check the new style cookie first
    cookieVal = req.cookies['3pcookie'];
  } else if (req.cookies['3pcookie-legacy']) {
    // otherwise fall back to the legacy cookie
    cookieVal = req.cookies['3pcookie-legacy'];
  }

  res.end();
});

app.listen(process.env.PORT);

이 접근 방식을 사용하려면 중복 쿠키를 설정하고 쿠키를 설정하고 읽는 시점에서 변경하는 추가 작업을 수행해야 합니다. 그러나 동작과 관계없이 모든 브라우저를 다루고 서드 파티 쿠키가 계속 작동하도록 해야 합니다.

또는 Set-Cookie 헤더가 전송될 때 사용자 에이전트 문자열을 사용하여 클라이언트를 감지할 수 있습니다. 호환되지 않는 클라이언트 목록을 참고하고 플랫폼에 적합한 사용자 에이전트 감지 라이브러리(예: Node.js의 ua-parser-js 라이브러리)를 사용하세요. 이 접근 방식에서는 한 번만 변경하면 되지만 사용자 에이전트 스니핑으로 영향을 받는 모든 사용자를 포착하지 못할 수 있습니다.

언어, 라이브러리, 프레임워크에서 SameSite=None 지원

대부분의 언어와 라이브러리는 쿠키의 SameSite 속성을 지원합니다. 하지만 SameSite=None가 추가된 지 아직 얼마 되지 않았으므로 지금은 일부 표준 동작을 해결해야 할 수 있습니다. 이러한 동작은 GitHub의 SameSite 예시 저장소에 설명되어 있습니다.

도움 받기

쿠키는 웹의 모든 곳에서 사용되며, 특히 교차 사이트 사용 사례에서 개발팀이 사이트에서 쿠키를 설정하고 사용하는 위치를 완전히 파악하는 경우는 드뭅니다. 문제가 발생하면 누구도 처음 경험하는 문제일 수 있으므로 언제든지 문의해 주세요.