SameSite=Lax по умолчанию — уже в Chrome 80 stable (правда, пока не у всех)

    На днях внимательная коллега (спасибо, Лена) зарепортила странный баг — сервер нормально ставил куку в браузере, но обратно она не прилетала. Днём ранее всё работало, теперь же кука выставлялась, но спустя несколько секунд магическим образом пропадала (хотя должна держаться сутки). Воспроизводилось это всего у нескольких человек в команде и только в новом Chrome 80, но у остальных в Chrome точно такой же версии всё было в порядке. В других браузерах всё работало как часы. Мистика. Начали разбираться, и спустя какое-то время в консоли Chrome заметили предупреждение для заголовка ответа, устанавливающего куки:
    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.

    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 ввести 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

    Комментарии 7

      +4

      Ага только не во всех браузерах SameSite=None; работает, так же как в новом Chrome. Так что нужен еще фильтр по UA. Потом, кто придумал, что там всегда должно быть Secure. Это вообще не понятно. Если я отдал куки по HTTP, то хочу по HTTP и получить. А вот разработчики Chrome придумали, что так нельзя. Привет, тепер у тебя куча лишнего геморроя с HTTPS для того чтобы запустить и протестить что то локально. Ясно что можно выключить в настройках браузера… Но это пока.

        +1

        Куки с SameSite=None должны быть Secure потому, что Pervasive Monitoring Is an Attack, а в прикладном смысле это выражается в Incrementally Better Cookies.


        Привет, тепер у тебя куча лишнего геморроя с HTTPS для того чтобы запустить и протестить что то локально.

        У меня, конечно, искажённое восприятие, но мне кажется, что не особенно тяжело поднять локальный HTTPS. Один раз сгенерировать себе локальный корневой сертификат и потом одной командой создавать локально доверенные сертификаты кажется мне не намного более сложным, чем IDE настроить.

          +1

          Кажется. Случаи разные бывают. Например, если в проде сервер работает через реверс прокси, а теперь только для отладки чего-то мне это надо локально подымать. И объяснять 100 разработчикам, как это делать. Сделаем конечно, но геморрой реально лишний. Потом этот корневой сертификат, надо где-то хранить, но так чтобы он потом не попал случайно в прод, и одновременно должен быть доступен всем для установки в браузер. А желательно чтоб он там был на девелоперских браузерах сразу. В общем несколько новых бизнес процессов на ровном месте.

          0
          не во всех браузерах SameSite=None; работает, так же как в новом Chrome

          Вот такой информации у меня нет. В старых браузерах SameSite не поддерживается совсем, но ведь это не значит что они не смогут использовать ресурсы, завязанные на куки. Наоборот, они будут отправлять куки всем.

          Или Вы о чём-то другом?
              +1

              Ну старые версии Chrome ладно оно везде обновляется, но мобильные WebView — привет от пользователей, которые имеют не самые свежие телефоны. И не только телефоны. У нас отвалились мобильные терминалы на Android у клиентов. Конечно в тестах. В проде пока вырубили SameSite=None;, сделаем настройку, чтоб включать только там где надо и ничего не поломается. Привет еще одна настройка за которой надо следить.

                0
                Спасибо, получается что некоторые старые версии Хрома не принимают куки с SameSite=None, не знал этого. Вечером добавлю в статью.

          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

          Самое читаемое