Recetas de galletas de SameSite

Chrome, Firefox, Edge y otros cambiarán su comportamiento predeterminado en línea con la propuesta de IETF Mejoras incrementales de las cookies para lo siguiente:

  • Las cookies sin un atributo SameSite se tratarán como SameSite=Lax, lo que significa que el comportamiento predeterminado será restringir las cookies a contextos propios únicamente.
  • Las cookies para el uso entre sitios deben especificar SameSite=None; Secure para permitir la inclusión en un contexto de terceros.

Esta función es el comportamiento predeterminado a partir de la versión estable de Chrome 84. Si aún no lo hiciste, debes actualizar los atributos de las cookies de terceros para que no se bloqueen en el futuro.

Compatibilidad con varios navegadores

Consulta la sección Compatibilidad del navegador de la página Set-Cookie de MDN.

Casos de uso de cookies entre sitios o de terceros

Hay una serie de casos de uso y patrones comunes en los que se deben enviar cookies en un contexto de terceros. Si proporcionas uno de estos casos de uso o dependes de ellos, asegúrate de que tú o el proveedor actualicen sus cookies para garantizar que el servicio siga funcionando correctamente.

Contenido dentro de una <iframe>

El contenido de un sitio diferente que se muestra en una <iframe> está en un contexto de terceros. Estos son los casos de uso estándar:

  • Contenido incorporado que se comparte desde otros sitios, como videos, mapas, muestras de código y publicaciones en redes sociales
  • Widgets de servicios externos, como pagos, calendarios y funciones de reserva y reserva
  • Widgets, como botones de redes sociales o servicios contra fraudes que crean <iframes> menos evidentes

Aquí se pueden usar cookies para, entre otras cosas, mantener el estado de la sesión, almacenar preferencias generales, habilitar estadísticas o personalizar el contenido para los usuarios con cuentas existentes.

Diagrama de una ventana del navegador donde la URL del contenido incorporado no coincide con la de la página.
Si el contenido incorporado no proviene del mismo sitio que el contexto de navegación de nivel superior, es contenido de terceros.

Además, como la Web es componible de forma inherente, se usan <iframes> para incorporar contenido que también se ve en un contexto propio o de nivel superior. Todas las cookies que use ese sitio se considerarán como cookies de terceros cuando el sitio se muestre en el marco. Si creas sitios que otros usuarios pueden incorporar con facilidad y, al mismo tiempo, dependen de las cookies para funcionar, también deberás asegurarte de que estén marcados para su uso entre sitios o de que puedas resguardarlos sin ellos.

Solicitudes "no seguras" en diferentes sitios

Aunque, en este caso, “no seguro” puede sonar un poco preocupante, esto se refiere a cualquier solicitud que podría tener la intención de cambiar el estado. En la Web, se trata principalmente de solicitudes POST. Las cookies marcadas como SameSite=Lax se enviarán en las navegaciones seguras de nivel superior, p.ej., cuando se haga clic en un vínculo para ir a un sitio diferente. Sin embargo, algo como un envío de <form> a través de POST a un sitio diferente no incluiría cookies.

Diagrama de una solicitud que pasa de una página a otra
Si la solicitud entrante usa un método "seguro", se enviarán las cookies.

Este patrón se usa para los sitios que pueden redireccionar al usuario a un servicio remoto para realizar alguna operación antes de regresar, por ejemplo, el redireccionamiento a un proveedor de identidad externo. Antes de que el usuario abandone el sitio, se configura una cookie que contiene un solo token de uso con la expectativa de que este token se pueda verificar en la solicitud que se muestra para mitigar los ataques de falsificación de solicitudes entre sitios (CSRF). Si esa solicitud que se muestra proviene de POST, será necesario marcar las cookies como SameSite=None; Secure.

Recursos remotos

Cualquier recurso remoto en una página puede depender de las cookies que se enviarán con una solicitud, desde las etiquetas <img>, las etiquetas <script>, etcétera. Algunos casos de uso comunes son el seguimiento de píxeles y la personalización del contenido.

Esto también se aplica a las solicitudes que fetch o XMLHttpRequest inicia desde tu JavaScript. Si se llama a fetch() con la opción credentials: 'include', es un buen indicador de que se podrían esperar cookies en esas solicitudes. Para XMLHttpRequest, debes buscar instancias de la propiedad withCredentials que se configuren como true. Esta es una buena indicación de que se podrían esperar cookies en esas solicitudes. Esas cookies deberán estar marcadas de forma adecuada para que se incluyan en solicitudes entre sitios.

Contenido dentro de WebView

Una WebView en una app específica de la plataforma funciona con un navegador, y deberás probar si se aplican las mismas restricciones o problemas. En Android, si WebView usa la tecnología de Chrome, los nuevos valores predeterminados no se aplicarán de inmediato con Chrome 84. Sin embargo, el intent es aplicarlos en el futuro, por lo que aún debes probarlos y prepararte. Además, Android permite que las apps específicas de su plataforma configuren cookies directamente a través de la API de CookieManager. Al igual que con las cookies establecidas a través de encabezados o JavaScript, considera incluir SameSite=None; Secure si están diseñadas para el uso entre sitios.

Cómo implementar SameSite hoy mismo

Para las cookies en las que solo se necesitan en un contexto propio, lo ideal es que las marques como SameSite=Lax o SameSite=Strict, según tus necesidades. También puedes optar por no hacer nada y solo permitir que el navegador aplique la configuración predeterminada, pero esto implica el riesgo de comportamiento incoherente en los navegadores y posibles advertencias de la consola por cada cookie.

Set-Cookie: first_party_var=value; SameSite=Lax

En el caso de las cookies necesarias en un contexto de terceros, deberás asegurarte de que estén marcadas como SameSite=None; Secure. Ten en cuenta que necesitas ambos atributos juntos. Si solo especificas None sin Secure, se rechazará la cookie. Sin embargo, existen algunas diferencias mutuamente incompatibles en las implementaciones de navegadores, por lo que es posible que debas usar algunas de las estrategias de mitigación que se describen en la sección Cómo manejar clientes incompatibles a continuación.

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

Cómo manejar clientes incompatibles

Como estos cambios para incluir None y actualizar el comportamiento predeterminado son relativamente nuevos, hay inconsistencias entre los navegadores en cuanto a cómo se manejan estos cambios. Puedes consultar la página de actualizaciones en chromium.org para conocer los problemas conocidos en este momento. Sin embargo, no es posible indicar si esta información es exhaustiva. Si bien esto no es ideal, existen soluciones alternativas que puedes emplear durante esta fase de transición. Sin embargo, la regla general es tratar a los clientes incompatibles como el caso especial. No crees una excepción para los navegadores que implementen las reglas más recientes.

La primera opción es configurar las cookies de estilo nueva y las antiguas:

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

Los navegadores que implementen el comportamiento más reciente configurarán la cookie con el valor SameSite, mientras que otros podrían ignorarla o configurarla de forma incorrecta. Sin embargo, esos mismos navegadores configurarán la cookie 3pcookie-legacy. Cuando procesa las cookies incluidas, el sitio primero debe verificar la presencia de la cookie de estilo nuevo y, si no la encuentra, recurrir a la cookie heredada.

En el siguiente ejemplo, se muestra cómo hacerlo en Node.js, con el framework Express y su middleware 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);

La desventaja es que esto implica configurar cookies redundantes para que cubran todos los navegadores y requiere realizar cambios en el momento de la configuración y la lectura de la cookie. Sin embargo, este enfoque debe abarcar todos los navegadores, independientemente de su comportamiento, y garantizar que las cookies de terceros sigan funcionando como antes.

Como alternativa, cuando envías el encabezado Set-Cookie, puedes elegir detectar el cliente a través de la string de usuario-agente. Consulta la lista de clientes incompatibles y, luego, usa una biblioteca adecuada para tu plataforma, por ejemplo, la biblioteca ua-parser-js en Node.js. Te recomendamos que busques una biblioteca para controlar la detección del usuario-agente, ya que probablemente no quieras escribir esas expresiones regulares por tu cuenta.

El beneficio de este enfoque es que solo requiere hacer un cambio en el momento de configurar la cookie. Sin embargo, la advertencia necesaria es que el sniffing del usuario-agente es inherentemente frágil y es posible que no detecte a todos los usuarios afectados.

Compatibilidad con SameSite=None en lenguajes, bibliotecas y frameworks

La mayoría de los lenguajes y las bibliotecas admiten el atributo SameSite para las cookies. Sin embargo, la adición de SameSite=None aún es relativamente nueva, lo que significa que, por el momento, es posible que debas solucionar parte del comportamiento estándar. Esto se documenta en el repositorio de ejemplos de SameSite en GitHub.

Cómo obtener ayuda

Las cookies están por todas partes y no es común que ningún sitio audite por completo dónde se configuran y usan, especialmente cuando se incluyen casos de uso entre sitios. Cuando tienes un problema, puede que sea la primera vez que alguien lo encuentra, así que no dudes en comunicarte con nosotros: