Receitas de cookies SameSite

O Chrome, Firefox, Edge e outros produtos vão mudar o comportamento padrão de acordo com a proposta do IETF, Cookies incrementalmente melhores para que:

  • Cookies sem um atributo SameSite serão tratados como SameSite=Lax, o que significa que o comportamento padrão será restringir cookies apenas a contextos primários.
  • Os cookies para uso entre sites precisam especificar SameSite=None; Secure para permitir a inclusão no contexto de terceiros.

Esse é o comportamento padrão do Chrome 84 estável em diante. Atualize os atributos dos cookies de terceiros para que eles não sejam bloqueados no futuro, caso ainda não tenha feito isso.

Suporte a vários navegadores

Consulte a seção Compatibilidade do navegador da página Set-Cookie do MDN.

Casos de uso de cookies entre sites ou de terceiros

Há vários casos de uso e padrões comuns em que os cookies precisam ser enviados em um contexto de terceiros. Se você fornece ou depende de um desses casos de uso, verifique se você ou o provedor estão atualizando os cookies para garantir que o serviço continue funcionando corretamente.

Conteúdo em uma <iframe>

O conteúdo de um site diferente exibido em um <iframe> está em um contexto de terceiros. Estes são os casos de uso padrão:

  • Conteúdo incorporado de outros sites, como vídeos, mapas, exemplos de código e postagens em redes sociais.
  • Widgets de serviços externos, como pagamentos, agendas, agendamentos e funcionalidades de reserva.
  • Widgets, como botões de redes sociais ou serviços antifraude, que criam uma <iframes> menos óbvia.

Os cookies podem ser usados aqui para, entre outras coisas, manter o estado da sessão, armazenar preferências gerais, ativar estatísticas ou personalizar conteúdo para usuários com contas existentes.

Diagrama de uma janela do navegador em que o URL do conteúdo incorporado não corresponde ao URL da página.
Se o conteúdo incorporado não vier do mesmo site que o contexto de navegação de nível superior, ele será de terceiros.

Além disso, como a Web é inerentemente combinável, as <iframes> são usadas para incorporar conteúdo que também é visualizado em um contexto próprio ou de nível superior. Todos os cookies usados por esse site serão considerados cookies de terceiros quando o site for exibido dentro do frame. Se você está criando sites que pretende ser facilmente incorporado por outras pessoas e, ao mesmo tempo, depende de cookies para funcionar, também é necessário garantir que eles sejam marcados para uso entre sites ou que você pode substituir sem eles.

Solicitações "não seguras" entre sites

Embora "não seguro" possa parecer um pouco preocupante, isso se refere a qualquer solicitação que possa ter a finalidade de mudar o estado. Na Web, trata-se principalmente de solicitações POST. Os cookies marcados como SameSite=Lax são enviados em navegações seguras de nível superior, por exemplo, ao clicar em um link para acessar outro site. No entanto, algo como um envio de <form> via POST para um site diferente não incluiria cookies.

Diagrama de uma solicitação passando de uma página para outra.
Se a solicitação recebida usar um método "seguro", os cookies serão enviados.

Esse padrão é usado em sites que podem redirecionar o usuário a um serviço remoto para executar alguma operação antes de retornar, por exemplo, redirecionar a um provedor de identidade de terceiros. Antes de o usuário sair do site, um cookie é definido com um token de uso único com a expectativa de que esse token possa ser verificado na solicitação de retorno para reduzir ataques de falsificação de solicitações entre sites (CSRF, na sigla em inglês). Se essa solicitação de retorno vier por POST, será necessário marcar os cookies como SameSite=None; Secure.

Recursos remotos

Qualquer recurso remoto em uma página pode depender de cookies para serem enviados com uma solicitação, de tags <img>, tags <script> e assim por diante. Casos de uso comuns incluem pixels de rastreamento e personalização de conteúdo.

Isso também se aplica a solicitações iniciadas no seu JavaScript por fetch ou XMLHttpRequest. Se fetch() for chamado com a opção credentials: 'include', essa é uma boa indicação de que os cookies podem ser esperados nessas solicitações. Para XMLHttpRequest, procure instâncias da propriedade withCredentials definida como true. Essa é uma boa indicação de que os cookies podem ser esperados nessas solicitações. Esses cookies precisarão ser marcados corretamente para serem incluídos em solicitações entre sites.

Conteúdo em uma WebView

Uma WebView em um app específico da plataforma é alimentada por um navegador. Você precisará testar se as mesmas restrições ou problemas se aplicam. No Android, se a WebView tiver a tecnologia do Chrome, os novos padrões não serão aplicados imediatamente com o Chrome 84. No entanto, a intenção é aplicá-los no futuro. Por isso, você ainda precisa testar e se preparar para isso. Além disso, o Android permite que apps específicos da plataforma definam cookies diretamente usando a API CookieManager. Assim como os cookies definidos por cabeçalhos ou JavaScript, inclua SameSite=None; Secure se eles forem destinados ao uso entre sites.

Como implementar o SameSite hoje mesmo

Para cookies em que eles são necessários apenas em um contexto próprio, o ideal é marcá-los como SameSite=Lax ou SameSite=Strict, dependendo das suas necessidades. Você também pode optar por não fazer nada e apenas permitir que o navegador aplique o padrão, mas isso traz o risco de comportamento inconsistente nos navegadores e possíveis avisos do console para cada cookie.

Set-Cookie: first_party_var=value; SameSite=Lax

Para cookies necessários em um contexto de terceiros, eles precisam estar marcados como SameSite=None; Secure. Você precisa dos dois atributos juntos. Se você especificar apenas None sem Secure, o cookie será rejeitado. No entanto, há algumas diferenças incompatíveis entre si nas implementações do navegador. Por isso, talvez seja necessário usar algumas das estratégias de mitigação descritas em Como lidar com clientes incompatíveis abaixo.

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

Como lidar com clientes incompatíveis

Como essas mudanças para incluir None e atualizar o comportamento padrão ainda são relativamente novas, há inconsistências entre os navegadores sobre como elas são processadas. Consulte a página de atualizações em chromium.org (em inglês) para os problemas conhecidos atualmente. No entanto, não é possível afirmar se isso está completo. Embora isso não seja o ideal, há soluções alternativas que podem ser empregadas durante essa fase de transição. No entanto, a regra geral é tratar clientes incompatíveis como o caso especial. Não crie uma exceção para navegadores que implementarem as regras mais recentes.

A primeira opção é definir os cookies de estilo novo e antigo:

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

Os navegadores que implementarem o comportamento mais recente definirão o cookie com o valor SameSite, enquanto outros navegadores podem ignorá-lo ou defini-lo incorretamente. No entanto, esses mesmos navegadores definem o cookie 3pcookie-legacy. Quando o processamento inclui cookies, o site deve verificar primeiro a presença do novo cookie de estilo e, se ele não for encontrado, substituir o cookie legado.

O exemplo abaixo mostra como fazer isso no Node.js, usando o framework Express e o middleware cookie-parser dele.

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);

A desvantagem é que isso envolve a configuração de cookies redundantes para cobrir todos os navegadores e exige mudanças na configuração e na leitura do cookie. No entanto, essa abordagem precisa abranger todos os navegadores, independentemente do comportamento deles, e garantir que os cookies de terceiros continuem funcionando como antes.

Como alternativa, ao enviar o cabeçalho Set-Cookie, é possível detectar o cliente pela string do user agent. Consulte a lista de clientes incompatíveis e use uma biblioteca apropriada para sua plataforma, por exemplo, ua-parser-js em Node.js. É aconselhável encontrar uma biblioteca para processar a detecção de user agent, já que você provavelmente não quer escrever essas expressões regulares.

A vantagem dessa abordagem é que ela requer apenas uma alteração no momento da configuração do cookie. No entanto, o aviso necessário aqui é que a detecção do user agent é inerentemente frágil e pode não capturar todos os usuários afetados.

Suporte para SameSite=None em linguagens, bibliotecas e frameworks

A maioria dos idiomas e bibliotecas oferece suporte ao atributo SameSite para cookies. No entanto, a adição de SameSite=None ainda é relativamente nova, o que significa que você pode precisar contornar alguns dos comportamentos padrão por enquanto. Eles estão documentados no repositório de exemplos do SameSite no GitHub.

Receber ajuda

Os cookies estão por toda parte, e é raro que um site faça uma auditoria completa do local em que são definidos e usados, especialmente quando você inclui casos de uso entre sites. Quando você encontra um problema, pode ser a primeira vez que alguém o encontra. Portanto, não hesite em entrar em contato: