Login em Iframe, Cookies, PHP, Https e SameSite

Recentemente precisei realizar uma integração entre um site e um software PHP onde o software seria exibido via Iframe dentro do site em WordPress.

O adicional neste caso era a necessidade de o login no software funcionasse dentro do Iframe. E não funcionou.

O PHP não consegue entender o login dentro de um Iframe?

Não há nenhuma relação específica com o PHP neste caso. O problema ocorre por conta da maneira como os navegadores de internet interpretam os cookies de sessão dentro de um Iframe em anos mais recentes.

E o PHP (e muitos outros softwares web) dependem de cookies de sessão para conseguir entender que aquela requisição corresponde aquele usuário logado em específico.

Cookies primários e de terceiros

Um cookie é uma informação “par=valor” salva no navegador de internet e que está associada com um domínio.

Ao acessar, por exemplo, youtube.com, o Youtube gravará um (ou mais) cookies no seu navegador para saber a cada atualização de páginas que é você que está navegando.

Um cookie é gravado no navegador como um cabeçalho de resposta de uma requisição. Ou seja, se você abrir uma aba anônima e digitar no navegador youtube.com, neste momento não há nenhum cookie salvo para este domínio e você com certeza aparecerá “deslogado”. A partir do momento em que você colocou o login e senha, se a autenticação foi bem sucedida o youtube.com mandará na resposta da requisição um cabeçalho que informará ao navegador para salvar um cookie de sessão informando que você é esse usuário logado.

Durante esta sessão de navegação, se você abrir novas abas, continuará logado porque o cookie está no navegador de internet, não na aba. E enquanto o domínio na barra do navegador for o mesmo domínio do cookie, dizemos que este cookie é primário, ou seja, ele é o mesmo do domínio principal do navegador, ou seja, o navegador pode liberar o acesso irrestrito para este cookie.

Mas o que acontece quando dentre de uma página, digamos, meu-site.com eu colocar um vídeo do Youtube como “embed“, ou seja, como um iframe?

A url do iframe será youtube.com. Porém, a url no navegador do usuário, a url principal, a url que o usuário enxerga é meu-site.com.

Neste caso, os cookies que o youtube.com tentar gravar ou acessar serão considerados cookies de acesso de terceiros.

Essa diferenciação é fundamental para compreender riscos de segurança e problemas de monitoramento e privacidade que estão envolvidos no uso dos cookies.

Aumentando segurança no uso dos cookies em toda a web

Nos primórdios do uso dos cookies não havia essa distinção, assim, embora o meu-site.com nunca tivesse tido a possibilidade de acessar os cookies de youtube.com, o meu-site.com se embutisse qualquer iframe ou acesso à API do domínio youtube.com teria sucesso.

E foi por isso que a partir da versão 80 do Google Chrome uma grande mudança começou a ser feita na maneira como os navegadores interpretam os cookies para que houvesse mais segurança por padrão, ou seja, para que por padrão, todos os cookies só pudessem ser acessados de forma primária, ou seja, somente quando o endereço na barra do navegador é o mesmo do cookie. O acesso a cookies a partir de um site na url do navegador diferente seria bloqueado por padrão.

Aprofundamento

Alguns casos de uso de cookies em contexto de terceiros

Segue uma lista casos de uso onde os cookies são vistos como cookies de terceiros e que sem as novas medidas de segurança, poderiam gerar vulnerabilidades.

  • Iframes;
  • Requisições post (inseguras) de um site para outro domínio (com cookies SameSite=Lax é possível que links e requisições GET recebam os cookies, mas requisições POST nunca);

Como os Navegadores Interpretam os Cookies em Iframes?

Este artigo (em inglês) explicará com muitos detalhes o que vou tratar neste capítulo. Aqui, segue um resumo.

Quando acessamos youtube.com o youtube cria um cookie de sessão que identifica o seu login. Isso é o acesso ao cookie em primeiro nível.

Quando temos um site que faz um embed do youtube.com, este embed do youtube deve poder ler o mesmo cookie de quando um usuário acessa o youtube diretamente? Durante muito tempo esse foi o padrão, mas como explicado neste artigo, isso abre muitas brechas de segurança.

Assim, o que importa daqui em diante é saber que os cookies dentro de sites com iframe são tratados neste caso como cookies de terceiros. E hoje, cookies de terceiros não são mantidos pelos navegadores por padrão.

Digo hoje, porque por muito tempo os cookies não tinham um cuidado de segurança. Isso gerou inclusive uma atualização tão importante no Google Chrome versão 80 que exigiu mudanças em muitos softwares sobre a maneira como os navegadores passariam a interpretar os cookies. Aqui um exemplo de como o Heroku orientou a mudança aos seus clientes.

Existe um atributo chamado SameSite nos cookies que pode ser configurado para Strict, Lax ou None. Lax e Strict tem uma leve diferença entre eles, mas ambos são formas seguras, onde somente acessando diretamente o próprio site é possível trabalhar com o cookie. Ou seja, não funcionará com iframe de um domínio diferente.

O “None” em tese permite que o cookie possa ser lido por diferentes domínios e em “tese” funcionaria para o uso dos iframes. É basicamente o comportamento “antigo”.

Porém, o cookie “None” só funciona quando o cookie é marcado como seguro. E o cookie só é marcado como seguro em requisições https.

Porém, o uso de cookies como “None”, mesmo em ambiente https não funciona por padrão no Safari do Mac e também não no Chrome do IPhone porque o Chrome do Iphone utiliza o AppleKit.

Diferença entre Lax e Strict

Quando fazemos uma requisição para um site. Seja via iframe, imagem, link, formulário ou AJAX, o navegador precisa decidir se envia os cookies associados com aquele domínio junto na requisição, ou não.

Já vimos que por questões de maior segurança o padrão hoje é o uso do valor Lax e que o uso do valor “None” deve ser informado propositadamente e que seu uso é muito mais inseguro.

Mas vamos entender isso melhor do ponto de vista do navegador.

  • None: Quando um cookie é marcado como none ele é enviado para o domínio de uma requisição (seja imagem, API, Iframe, etc) sempre que uma requisição for feita para aquele domínio sem se importar com o que está na barra de endereço do usuário. Embora seja super inseguro é bom lembrar que é assim que as coisas funcionavam por padrão até poucos anos atrás;
  • Lax: O lax só envia um cookie para um domínio se o endereço que irá aparecer na barra de busca de usuário for o mesmo do cookie. “IRÁ” é a palavra importante aqui. Quando eu estou em meu-site.com e clico em um link para youtube.com esta primeira requisição para youtube.com irá receber os cookies marcados como Lax de youtube.com, e com isso, você já aparecerá logado logo que acessar a página do Youtube. Isso previne vários problemas de segurança como iframes, chamadas para API de sites externos, etc. Outra restrição é chamadas de formulário POST. É possível criar um formulário cujo atributo action aponte para outro site. Estas requisições, embora o seu resultado será o site youtube.com na barra de endereço do navegador, não irão enviar o cookie junto para evitar que um site malicioso tente simular um formulário do próprio youtube ou qualquer outro site. Assim, Lax já é seguro.
  • Strict: A propriedade strict é ainda mais rígida. Todos os cookies marcados como Strict só serão enviados para o seu site proprietário na segunda requisição. Ou seja, se o youtube.com usasse cookies em modo estrito e eu clicasse em um link do meu site para o Youtube eu não apareceria logado no primeiro acesso de jeito nenhum, porque nesta primeira requisição os cookies não teriam sido enviados. Somente após um F5 ou após clicar em algum link da página do youtube que os links seriam enviados. É como dizer para o browser que o cookie só pode ser enviado, quando Strict, se a origem da requisição – e não somente o destino – forem o mesmo domínio proprietário do cookie.

Mas qual a vantagem de usar “Strict” ao invés de “Lax”? Nesta resposta do Stack Overflow tem alguns pontos levantados:

  • Se um site é mal implementado e possui requisições GET que fazem persistência de dados, o modo Strict é a única forma de prevenir formulários e chamadas de outros sites e de API’s de impactaram os dados de um usuário logado;
  • Existem formas de ataques mais refinadas que podem ser protegidas pelo modo “strict”;
  • Ele pode ser útil também para features muito específicas que você queira garantir que só aconteçam vindo do seu próprio site;
  • E para evitar que mesmo que suas API’s GET que não modificam estado mas dependem de sessão não sejam acessadas por sites de terceiros.

No geral “Lax” vai funcionar perfeitamente para sites e aplicações de conteúdo enquanto softwares SaaS ou softwares legados mais vulneráveis podem se beneficiar de um uso mais estrito.

Por que a Apple bloqueia estes cookies por padrão?

Durante muitos anos Facebook e Google se beneficiaram muito do uso de iframes com cookies para monitorar os sites onde os usuários navegam na internet.

Cada vez que um site fazia o “embed” de um botão do facebook ou de um anúncio com AdSense via o uso destes cookies era possível para Google e Facebook saber se um usuário passou por estes sites com algum destes botão ou anúncio.

Isso vale também para todos os sites com conteúdo embed, como o próprio Youtube.

Isso permitiu até então um altíssimo nível de monitoramento dos usuários pela internet de forma muito personalizada.

Com as provocações sobre privacidade aos poucos os navegadores foram adicionando restrições a esta prática.

A própria exigência do https para os cookies foi um destes passos.

E outro passo importante dando pela Apple foi NEGAR, por PADRÃO qualquer cookie de terceiros. Assim, a partir da versão 14 dos softwares da Apple os cookies de terceiros não funcionam e isso inviabiliza o uso tradicional de iframe nas sessões.

Essa mudança provocou bastante movimento na indústria no início de 2020, mas não é algo exclusivo da Apple.

É o fim dos cookies de terceiros?

Parece que sim. Inclusive a Google, uma das maiores beneficiárias da prática deve adotar essa opção por padrão até algum momento de 2023.

O ideal portanto é buscar outras práticas de construção que não dependam de um login via Iframe.

Até é possível desabilitar a opção nas configurações do Iphone ou do Safari, porém, é inadequado esperar em qualquer produto com um volume de usuários maior ou que tenha uma característica de acesso esporádico que essa seja uma solução adequada.

Do ponto de vista do marketing isso interfere muito na forma de fazer propaganda digital e existem abordagens para lidar com o tema como mostrado neste outro artigo.

Mas preciso muito fazer login no iframe, o que devo fazer?

Ainda não testei, mas parece que a única solução é que esta integração aconteça em um subdomínio do domínio principal. Com isso o cookie pode ser tratado como um cookie de mesmo site.

Temos aqui no stack overflow uma resposta sobre esta questão e este conteúdo da Think Tecture tem dois links logo no início que parecem ir mais a fundo neste tema.