Safari 13+ iframe bloqueia cookies CORS

9

O Safari não permite que você defina cookies em iframes de domínios diferentes do domínio pai, cabeçalhos CORS do servidor.

Para esclarecer: o usuário está em domainA.com. Um iframe para domainB.com está aberto e tenta autenticar o usuário em domainB.com dentro do iframe. O cabeçalho Set-Cookie é retornado do servidor dentro do iframe domainB.com, com todos os cabeçalhos necessários, mas o Safari não o envia de volta nas chamadas subseqüentes.

Uma solução alternativa antiga estava enviando um formulário a partir do iframe e configurava o cookie na resposta. Acho que eles gostaram do fato de o usuário estar clicando em algo para enviar o formulário. Você precisaria pesquisar o cookie para ver quando a resposta retornaria, pois os envios de formulários não têm retorno de chamada e, no caso dos cookies HttpOnly, você não podia, mas, ei, funcionou! Até que não.

Em seguida, uma solução alternativa mais recente foi redirecionar o usuário para o domínio iframe em uma nova janela / guia, definindo um cookie aleatório e, a partir desse momento, esse subdomínio foi "confiável" dentro do iframe. Novamente, foi necessário um clique para abrir a nova janela / guia, e havia até uma indicação visual da nova abertura da guia. Muita segurança, esses padrões.

E agora, a partir do Safari 13 - Não há mais solução alternativa. Nenhuma configuração de cookie iframe mais segura 🤬

Qualquer outro esquema de autenticação não é bom para nós (por exemplo, cabeçalho Auth-X). Precisamos usar um cookie seguro HttpOnly, pois não queremos que o token seja acessível de maneira alguma pelo javascript do lado do cliente.

Para ser claro, tudo funciona muito bem em qualquer outro navegador.

WebKit Bugzilla relevante

Alguém tem alguma sugestão?

Editar:

Obrigado pelo link @tomschmidt, que parece a direção certa. Tentei usar a API de acesso à armazenamento da Apple, mas infelizmente solicitei acesso antes de inicializar minha lógica de login com a API:

requestStorageAccess = async() => {
    return new Promise(resolve => {
      //@ts-ignore
      document.requestStorageAccess().then(
        function () {
          console.log('Storage access was granted');
          resolve(true);
        },
        function () {
          console.log('Storage access was denied');
          resolve(false);
        }
      );    
    });
  }


const storageAccessGranted = await requestStorageAccess();
console.log(storageAccessGranted) // prints 'true'
await login();

Ainda assim, os cookies recebidos na resposta da API / login não estão sendo enviados nas chamadas subseqüentes à API :(

Tom Teman
fonte
Verifique se isso só é acionado em interação explícita com o iframe, como onclick.
tomschmidt 17/01
11
Sim, foi assim que eu fiz. Confira o problema do bugkit do webkit ao qual vinculei, acho que esse é um bug real no final do Safari: /
Tom Teman
O problema não é que os cookies não sejam enviados. Se você solicitar acesso ao armazenamento, os cookies existentes serão enviados ao servidor. O problema é que todos os novos cookies não são armazenados e, portanto, não existem para serem enviados.
Matt Cosentino
@MattCosentino, é isso que eu quis dizer - "cookies recebidos na resposta da API / login" são novos cookies que são enviados de volta na resposta do cabeçalho Set-Cookie ao domínio iframe, mas a próxima chamada do domínio iframe não inclui aqueles cookies na solicitação. Então, sim, é mais correto dizer que a raiz do problema é que nenhum novo cookie está sendo armazenado no navegador nesse cenário.
Tom Teman

Respostas:

1

Acho que encontrei a solução: API de acesso a armazenamento da Apple: https://webkit.org/blog/8124/introducing-storage-access-api/

tomschmidt
fonte
Ei, obrigado pela idéia, mas receio que não tenha funcionado (verifique minha resposta)
Tom Teman
11
Também estou tendo o mesmo problema com o safari 13. Alguma solução alternativa?
Niroshana
0

Portanto, a solução alternativa ainda funciona, desde que a nova janela esteja armazenando o cookie que você deseja armazenar. O iframe ainda não pode armazenar seus próprios cookies. No meu caso, tudo que eu precisava era do cookie de identificação da sessão. Portanto, abro uma pequena janela pop-up quando o usuário concede acesso ao armazenamento. Ele obtém e armazena o cookie de identificação da sessão, fecha e recarrega o iframe. O iframe então tem acesso ao cookie de identificação da sessão e o envia em solicitações subsequentes. Eu acho que isso é apenas temporário, parece que eles removerão o acesso ao armazenamento das janelas pop-up em algum momento no futuro. Talvez eles consertem o iframe não podendo armazenar cookies até então.

Matt Cosentino
fonte
Matt, usei uma solução semelhante com um pop-up, que funciona na área de trabalho Safari 13.1, mas o teste em um iPad Safari 13.4 não está funcionando. Você conseguiu fazer isso funcionar em um iPad? Thnx
teamdane