Советы по использованию файлов cookie с атрибутом SameSite
Обновите файлы cookie своего сайта, чтобы подготовиться к предстоящим изменениям в поведении атрибута SameSite.
Поведение Chrome, Firefox, Edge и других браузеров будет изменено в соответствии с предложением IETF Incrementally Better Cookies:
- Файлы cookie без атрибута
SameSite
будут обрабатываться так, как будто имеют атрибутSameSite=Lax
: по умолчанию они будут действовать исключительно в рамках собственного контекста. - Файлы cookie, предназначенные для межсайтового использования, должны включать атрибут
SameSite=None; Secure
, разрешающий использование в сторонних контекстах.
Это поведение является стандартным начиная со стабильной версии Chrome 84. Если вы еще не обновили атрибуты своих межсайтовых файлов cookie, вам следует это сделать, чтобы избежать их блокировки в будущем.
Поддержка в браузерах #
См. раздел Совместимость браузеров на странице о заголовке Set-Cookie
в MDN.
Примеры использования межсайтовых или сторонних файлов cookie #
Существует ряд распространенных случаев и сценариев использования, когда файлы cookie необходимо пересылать в стороннем контексте. Если ваш сайт фигурирует в роли поставщика или потребителя таких файлов cookie, проследите, чтобы либо вы, либо поставщик файлов cookie обновили их для обеспечения правильной работы в будущем.
Контент внутри элемента <iframe>
#
Контент с другого сайта, отображаемый внутри элемента <iframe>
, считается находящимся в стороннем контексте. Ниже перечислены стандартные сценарии использования:
- Встраиваемый контент с других сайтов, например видео, карты, фрагменты кода и посты из социальных сетей.
- Виджеты сторонних сервисов: календари, формы оплаты, бронирования, резервирования столиков и т. д.
- Виджеты, при использовании которых факт наличия
<iframe>
менее очевиден, например кнопки соцсетей или сервисы защиты от мошенничества.
В таких сценариях файлы cookie могут использоваться, помимо прочего, для сохранения состояния сеанса, хранения настроек, сбора статистики или персонализации контента для пользователей с существующими аккаунтами.
Кроме того, поскольку веб-страницы по своей природе являются встраиваемыми, элементы <iframe>
используются для встраивания контента, который также может просматриваться в своем родном контексте. Любые файлы cookie, используемые сайтом внутри iframe, будут обрабатываться как сторонние. Если страницы вашего сайта рассчитаны на то, чтобы их можно было легко встраивать на сторонние сайты, и при этом их функциональность зависит от файлов cookie, вам следует пометить файлы cookie как предназначенные для межсайтового использования или обеспечить корректную работу сайта при их отсутствии.
«Небезопасные» межсайтовые запросы #
Не следует пугаться слова «небезопасные»: оно всего лишь обозначает запросы, которые могут приводить к изменению состояния. В контексте веб-страниц это относится главным образом к POST-запросам. При безопасных переходах в главном окне, например в результате нажатия ссылки, ведущей на другой сайт, файлы cookie, помеченные как SameSite=Lax
, продолжают действовать. Однако небезопасные межсайтовые запросы, такие как отправка формы при помощи POST, не будут включать файлы cookie.
Это поведение используется на сайтах, которые временно перенаправляют пользователя на другой сайт с целью совершения операции (например, входа при помощи стороннего поставщика идентификации). Перед тем как пользователь покидает сайт, в его браузер устанавливается файл cookie с одноразовым токеном, а при возвращении пользователя этот токен проверяется, чтобы предотвратить атаки с межсайтовой подделкой запросов (CSRF). Если для возврата пользователя на сайт применяется POST-запрос, файлы cookie необходимо будет пометить как SameSite=None; Secure
.
Удаленные ресурсы #
Когда страница загружает удаленные ресурсы (теги <img>
, <script>
и т. д.), ей может понадобиться передать в запросе файлы cookie. Такая потребность может возникать при использовании отслеживающих пикселей или персонализации контента.
То же самое касается запросов, инициируемых из JavaScript-кода при помощи fetch
или XMLHttpRequest
. Если fetch()
вызывается с параметром credentials: 'include'
, то высока вероятность, что в запросе будут фигурировать файлы cookie. Что касается XMLHttpRequest
, то вам следует обратить внимание на свойство withCredentials
: если оно установлено в значение true
, это также говорит о том, что в запросе, скорее всего, используются файлы cookie. Такие файлы cookie необходимо будет пометить как предназначенные для межсайтовых запросов.
Контент внутри WebView #
WebView в платформозависимых приложениях используют в качестве основы браузер; проверьте, распространяются ли на них те же проблемы и ограничения. В Android новое поведение Chrome (по состоянию на версию 84) пока не распространяется на WebView, но в будущем это изменится, так что вам по-прежнему следует подготовиться и проверить совместимость с ним. Кроме того, Android позволяет платформозависимым приложениям устанавливать файлы cookie напрямую, используя CookieManager API. Как и в случае с файлами cookie, устанавливаемыми при помощи заголовков или JavaScript, используйте SameSite=None; Secure
, если файл предназначен для межсайтового применения.
Как реализовать SameSite
уже сегодня #
Файлы cookie, используемые только в собственном контексте, в идеале следует помечать как SameSite=Lax
или SameSite=Strict
в зависимости от потребностей. Вы также можете не указывать ничего, позволив браузеру использовать политику по умолчанию, однако это чревато риском несогласованного поведения между браузерами и потенциальным появлением в консоли предупреждений о каждом файле cookie.
Set-Cookie: first_party_var=value; SameSite=Lax
Файлы cookie, используемые в сторонних контекстах, необходимо помечать как SameSite=None; Secure
. Обратите внимание, что указывать нужно оба атрибута сразу. Если указать только None
без Secure
, файл cookie будет отклонен. Однако в реализациях браузеров присутствуют взаимно несовместимые различия, для обхода которых могут понадобиться способы, описанные в разделе Работа с несовместимыми клиентами.
Set-Cookie: third_party_var=value; SameSite=None; Secure
Работа с несовместимыми клиентами #
Поскольку решение добавить значение None
и изменить стандартное поведение было принято относительно недавно, в различных браузерах это изменение реализовано по-разному. Со списком известных проблем можно ознакомиться на chromium.org на странице об изменениях, однако список может быть неполным. Хотя такая ситуация не является идеальной, в течение переходного периода можно прибегать к временным решениям. Общее правило заключается в том, чтобы обрабатывать несовместимые клиенты как особый случай, а на создавать исключения для браузеров, следующих новым правилам.
Одно из возможных решений — устанавливать файлы cookie как в новом, так и в старом формате:
Set-cookie: 3pcookie=value; SameSite=None; Secure
Set-cookie: 3pcookie-legacy=value; Secure
Браузеры, в которых реализовано новое поведение, будут использовать файлы cookie с указанным SameSite
. В других браузерах такие файлы могут игнорироваться или устанавливаться некорректно, но при этом будет использоваться файл cookie 3pcookie-legacy
. При обработке файлов cookie, указанных в запросе, сайт должен сначала проверить наличие файла cookie нового образца и только в случае неудачи использовать файл cookie старого формата.
Ниже показан пример реализации такого поведения на 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);
Недостаток подхода заключается в том, что для обеспечения поддержки всех браузеров необходимо дублировать файлы cookie, а также вносить изменения в процесс их установки и считывания. Однако такой подход обеспечивает поддержку всех браузеров вне зависимости от их поведения, благодаря чему межсайтовые файлы cookie продолжают работать так же, как и раньше.
В качестве альтернативы можно определять версию клиента по строке User-Agent перед отправкой заголовка Set-Cookie
. Ознакомьтесь со списком несовместимых клиентов, а затем воспользуйтесь подходящей для вашей платформы библиотекой, например ua-parser-js для Node.js. Определение User-Agent при помощи сторонней библиотеки позволяет не тратить время на написание регулярных выражений для самостоятельного определения.
Преимущество такого подхода заключается в том, что вносить изменения требуется только в процесс установки файла cookie. Однако имейте в виду, что определение User-Agent по своей природе ненадежно и для части пользователей может давать неверный результат.
Поддержка SameSite=None
в различных языках, библиотеках и фреймворках #
Большинство языков и библиотек поддерживают файлы cookie с атрибутом SameSite
, однако параметр SameSite=None
появился относительно недавно, поэтому вам потребуются временные решения для обхода стандартного поведения. Они приведены в репозитории с примерами использования SameSite
на GitHub.
Как получить помощь #
Файлы cookie применяются повсюду, и мало кто проводит на сайтах полный аудит всех мест, где они устанавливаются и используются, особенно если учитывать межсайтовые сценарии. Столкнувшись с проблемой, имейте в виду, что ваш случай может быть первым в своем роде, и не стесняйтесь обращаться за помощью:
- Сообщите о проблеме в репозитории с примерами использования
SameSite
на GitHub. - Задайте вопрос с тегом «samesite» на StackOverflow.
- Если проблема связана с поведением Chromium, сообщите об ошибке, используя шаблон [SameSite cookies].
- Следите за ходом разработки Chrome на странице обновлений
SameSite
.