На днях внимательная коллега (спасибо, Лена) зарепортила странный баг — сервер нормально ставил куку в браузере, но обратно она не прилетала. Днём ранее всё работало, теперь же кука выставлялась, но спустя несколько секунд магическим образом пропадала (хотя должна держаться сутки). Воспроизводилось это всего у нескольких человек в команде и только в новом Chrome 80, но у остальных в Chrome точно такой же версии всё было в порядке. В других браузерах всё работало как часы. Мистика. Начали разбираться, и спустя какое-то время в консоли Chrome заметили предупреждение для заголовка ответа, устанавливающего куки:
Начали изучать что это такое, и постепенно стало понятно, как ошибка возникла и почему проявлялась не у всех. Поскольку наш сервис должен обрабатывать запросы с разных доменов, то
Изначально, по стандарту HTTP, браузер отправлял cookies (или просто куки) при любом запросе на соответствующий им домен. Это открывало возможности для CSRF-атаки, то есть позволяло недобросовестным людям при определённом стечении обстоятельств получить доступ к каким-либо ресурсам под видом ничего не подозревающих добросовестных, просто воспользовавшись их куками.
В 2016 году был введён атрибут
В мае 2019 года разработчики Google Chrome объявили, что будут постепенно менять это поведение и трактовать отсутствие SameSite как
Для пользователей такое поведение браузера более безопасно. Разработчикам же сайтов и веб-сервисов нужно иметь ввиду, что если им всё-таки требуется получать свои cookies при запросах с других сайтов, они должны будут явно установить своим кукам атрибуты
Поскольку нововведение меняет действующий стандарт, и не все сайты смогут адаптироваться быстро, то переход к новому поведению происходит постепенно. Изначально его включили у ограниченного числа бета-пользователей Chrome, и вот теперь постепенно увеличивают их количество. Актуальная информация доступна здесь. Самая свежая запись по ссылке:
Вернуть старое поведение возможно через настройки: в адресной строке Chrome ввести
Поэтому если вашему сайту требуется получать cookies при запросах с разных доменов — будьте готовы к грядущим переменам (а кто уже готов — тот молодец). Всем добра!
Дополнено:
xdenser в комментариях указал, что некоторые старые версии браузеров не поддерживают
Дополнено 2:
В связи с ситуацией с COVID-19, с 3 апреля 2020 г. Google временно приостанавливает внедрение описанных изменений в обработке SameSite, для обеспечения бесперебойной работы интернет-сервисов. На устройствах, где изменения уже задействованы, они будут отменены.
(с) blog.chromium.org/2020/04/temporarily-rolling-back-samesite.html
Источники:
web.dev/samesite-cookies-explained
www.chromium.org/updates/same-site
www.chromestatus.com/feature/5088147346030592
www.chromium.org/updates/same-site/incompatible-clients
blog.chromium.org/2020/04/temporarily-rolling-back-samesite.html
A cookie associated with a cross-site resource at _your_domain_ was set without the `SameSite` attribute. A future release of Chrome will only deliver cookies with cross-site requests if they are set with `SameSite=None` and `Secure`.
Начали изучать что это такое, и постепенно стало понятно, как ошибка возникла и почему проявлялась не у всех. Поскольку наш сервис должен обрабатывать запросы с разных доменов, то
SameSite
— как раз наш случай. Добавили SameSite=None; Secure
, и проблема для нас решилась.Почему так?
Изначально, по стандарту HTTP, браузер отправлял cookies (или просто куки) при любом запросе на соответствующий им домен. Это открывало возможности для CSRF-атаки, то есть позволяло недобросовестным людям при определённом стечении обстоятельств получить доступ к каким-либо ресурсам под видом ничего не подозревающих добросовестных, просто воспользовавшись их куками.
В 2016 году был введён атрибут
SameSite
, позволяющий контролировать, будет ли браузер отправлять cookies, если страница посылает запрос на другой домен. У разработчиков появилась возможность блокировать передачу своих кук, если запрос выполняется с постороннего сайта. Для этого атрибуту SameSite
нужно было явно присвоить значение Strict (cookies передаются только при запросах и переходах с домена, к которому они относятся), или Lax (куки передаются при переходе на сайт с других сайтов по прямой ссылке, но не передаются при других запросах с них, например при AJAX-запросе или загрузке картинок). Отсутствие SameSite
было эквивалентно SameSite=None
, то есть по умолчанию cookies всё так же передавались при любых запросах.В мае 2019 года разработчики Google Chrome объявили, что будут постепенно менять это поведение и трактовать отсутствие SameSite как
SameSite=Lax
(подробнее здесь). То есть — по умолчанию браузер будет блокировать передачу cookies при запросах с текущей страницы на любые другие ресурсы, кроме прямых переходов по ссылке. Разработчики Firefox и Edge объявили, что со временем так же внедрят это изменение в своих браузерах.Для пользователей такое поведение браузера более безопасно. Разработчикам же сайтов и веб-сервисов нужно иметь ввиду, что если им всё-таки требуется получать свои cookies при запросах с других сайтов, они должны будут явно установить своим кукам атрибуты
SameSite=None, Secure
(Secure
— потому что такой запрос вдобавок должен приходить на сервер только по защищённому каналу).Поскольку нововведение меняет действующий стандарт, и не все сайты смогут адаптироваться быстро, то переход к новому поведению происходит постепенно. Изначально его включили у ограниченного числа бета-пользователей Chrome, и вот теперь постепенно увеличивают их количество. Актуальная информация доступна здесь. Самая свежая запись по ссылке:
Last updated March 9, 2020.То есть, период бета-тестирования позади, и разработчики Chrome начали потихоньку включать новый функционал у обычных пользователей. Что в принципе хорошо, поскольку так действительно безопаснее.
We have begun enforcing the new behavior for Chrome 80 stable, just not for 100% of users. The controlled rollout is to a limited initial population,
Вернуть старое поведение возможно через настройки: в адресной строке Chrome ввести
chrome://flags
, перейти на страницу, найти пункт SameSite be default cookies, и установить ему значение Disabled. Но это подходит больше для тестирования, чем для простых пользователей. Аналогично, если в вашем Chrome 80 пока работает старое поведение, вы можете принудительно включить новый функционал, установив эту же настройку в Enabled.Поэтому если вашему сайту требуется получать cookies при запросах с разных доменов — будьте готовы к грядущим переменам (а кто уже готов — тот молодец). Всем добра!
Дополнено:
xdenser в комментариях указал, что некоторые старые версии браузеров не поддерживают
SameSite=None
, не принимая такие куки совсем или обрабатывая их нестандартным способом. Среди них есть браузеры для десктопов и мобильных устройств. На странице https://www.chromium.org/updates/same-site/incompatible-clients приводится список браузеров и возможное решение проблемы (на псевдокоде, но довольно детальное). Авторы предлагают детектировать проблемные версии браузеров по заголовку useragent
, и не выставлять их кукам атрибут SameSite=None
совсем.Дополнено 2:
В связи с ситуацией с COVID-19, с 3 апреля 2020 г. Google временно приостанавливает внедрение описанных изменений в обработке SameSite, для обеспечения бесперебойной работы интернет-сервисов. На устройствах, где изменения уже задействованы, они будут отменены.
(с) blog.chromium.org/2020/04/temporarily-rolling-back-samesite.html
Источники:
web.dev/samesite-cookies-explained
www.chromium.org/updates/same-site
www.chromestatus.com/feature/5088147346030592
www.chromium.org/updates/same-site/incompatible-clients
blog.chromium.org/2020/04/temporarily-rolling-back-samesite.html