API Storage Access

O bloqueio de cookies de terceiros por navegadores, configurações do usuário e particionamento de armazenamento é um desafio para sites e serviços que dependem de cookies e outros armazenamentos em contextos incorporados para jornadas do usuário, como autenticação. A API Storage Access (SAA) permite que esses casos de uso continuem funcionando, limitando o rastreamento entre sites o máximo possível.

Status da implementação

Compatibilidade com navegadores

  • Chrome: 119.
  • Edge: 85.
  • Firefox: 65.
  • Safari: 11.1.

Origem

A API Storage Access está disponível em todos os principais navegadores, mas há pequenas diferenças de implementação entre eles. Essas diferenças foram destacadas nas seções relevantes desta postagem.

O trabalho continua para resolver todos os problemas de bloqueio restantes antes de padronizar a API.

O que é a API Storage Access?

A API Storage Access é uma API JavaScript que permite que iframes solicitem permissões de acesso ao armazenamento, que, de outra maneira, seria negado de acordo com as configurações do navegador. As incorporação com casos de uso que dependem do carregamento de recursos entre sites podem usar a API para solicitar a permissão de acesso do usuário conforme necessário.

Se a solicitação de armazenamento for concedida, o iframe terá acesso aos cookies e ao armazenamento não particionados, que também estarão disponíveis quando os usuários o visitarem como um site de nível superior.

A API Storage Access permite que o acesso a cookies e armazenamento não particionados específicos seja fornecido com o mínimo de sobrecarga para o usuário final, além de impedir o acesso a cookies e armazenamento não particionados genéricos, que geralmente são usados para rastrear usuários.

Casos de uso

Alguns conteúdos incorporados de terceiros exigem acesso a cookies ou armazenamento não particionados para oferecer uma experiência melhor ao usuário. Isso não estará disponível quando os cookies de terceiros estiverem restritos e a partição de armazenamento estiver ativada.

Os casos de uso incluem o seguinte:

  • Widgets de comentários incorporados que exigem detalhes da sessão de login.
  • Botões "Curtir" de mídias sociais que exigem detalhes da sessão de login.
  • Documentos incorporados que exigem detalhes da sessão de login.
  • Uma experiência premium fornecida a uma incorporação de vídeo, por exemplo, para não mostrar anúncios para usuários conectados ou para saber as preferências do usuário em relação a legendas ou restringir determinados tipos de vídeo.
  • Sistemas de pagamento incorporados.

Muitos desses casos de uso envolvem o acesso persistente de login em iframes incorporados.

Quando usar a API Storage Access em vez de outras APIs

A API Storage Access é uma das alternativas para usar cookies e armazenamento não particionados. Por isso, é importante entender quando usar essa API em comparação com as outras. Ele é destinado a casos de uso em que as duas condições a seguir são verdadeiras:

  • O usuário vai interagir com o conteúdo incorporado, ou seja, não é um iframe passivo ou oculto.
  • O usuário visitou a origem incorporada em um contexto de nível superior, ou seja, quando essa origem não está incorporada em outro site.

Existem APIs alternativas para vários casos de uso:

  • Os cookies com estado particionado independente (CHIPS, na sigla em inglês) permitem que os desenvolvedores ativem um cookie para armazenamento "particionado", com um cookie jar separado por site de nível superior. Por exemplo, um widget de chat da Web de terceiros pode depender da configuração de um cookie para salvar informações da sessão. As informações da sessão são salvas por site, então o cookie definido pelo widget não precisa ser acessado em outros sites em que ele também está incorporado. A API Storage Access é útil quando um widget de terceiros incorporado depende do compartilhamento das mesmas informações em diferentes origens (por exemplo, para detalhes ou preferências de sessão de login).
  • O particionamento de armazenamento é uma maneira de iframes entre sites usarem mecanismos de armazenamento JavaScript existentes e dividir o armazenamento subjacente por site. Isso impede que o armazenamento incorporado em um site seja acessado pela mesma incorporação em outros sites.
  • Os conjuntos de sites relacionados (RWS, na sigla em inglês) são uma maneira que as organizações têm para declarar relações entre sites para que os navegadores permitam o acesso limitado de cookies não particionados e de armazenamento para fins específicos. Os sites ainda precisam solicitar acesso com a API Storage Access, mas, para os sites do conjunto, o acesso pode ser concedido sem solicitações do usuário.
  • O Gerenciamento de credenciais federadas (FedCM, na sigla em inglês) é uma abordagem que preserva a privacidade nos serviços de identidade federada. A API Storage Access lida com o acesso a cookies não particionados e ao armazenamento após o login. Para alguns casos de uso, o FedCM oferece uma solução alternativa à API Storage Access e pode ser preferível, já que apresenta uma solicitação de navegador mais orientada ao login. No entanto, a adoção do FedCM geralmente requer outras mudanças no código, por exemplo, para oferecer suporte aos endpoints HTTP.
  • As APIs antifraude, relacionadas a anúncios e de medição também existem, e a API Storage Access não tem a intenção de resolver essas questões.

Usar a API Storage Access

A API Storage Access tem dois métodos baseados em promessas:

Ela também se integra à API Permissions. Isso permite verificar o status da permissão de acesso ao armazenamento em um contexto de terceiros, o que indica se uma chamada para document.requestStorageAccess() seria concedida automaticamente:

Use o método hasStorageAccess()

Quando um site é carregado pela primeira vez, ele pode usar o método hasStorageAccess() para verificar se o acesso a cookies de terceiros já foi concedido.

// Set a hasAccess boolean variable which defaults to false.
let hasAccess = false;

async function handleCookieAccessInit() {
  if (!document.hasStorageAccess) {
    // Storage Access API is not supported so best we can do is
    // hope it's an older browser that doesn't block 3P cookies.
    hasAccess = true;
  } else {
    // Check whether access has been granted using the Storage Access API.
    // Note on page load this will always be false initially so we could be
    // skipped in this example, but including for completeness for when this
    // is not so obvious.
    hasAccess = await document.hasStorageAccess();
    if (!hasAccess) {
      // Handle the lack of access (covered later)
    }
  }
  if (hasAccess) {
    // Use the cookies.
  }
}
handleCookieAccessInit();

O acesso ao armazenamento só é concedido a um documento iframe depois que ele chama requestStorageAccess(),. Portanto, hasStorageAccess() sempre retornará falso inicialmente, exceto quando outro documento de mesma origem no mesmo iframe já tiver recebido acesso. O acesso é preservado em navegações de mesma origem dentro do iframe especificamente para permitir recarregar após conceder acesso a páginas que exigem que cookies estejam presentes na solicitação inicial do documento HTML.

Usar requestStorageAccess()

Se o iframe não tiver acesso, talvez seja necessário solicitar acesso usando o método requestStorageAccess():

if (!hasAccess) {
  try {
    await document.requestStorageAccess();
  } catch (err) {
    // Access was not granted and it may be gated behind an interaction
    return;
  }
}

Na primeira vez que isso for solicitado, o usuário poderá precisar aprovar esse acesso com uma solicitação do navegador. Depois disso, a promessa será resolvida ou rejeitada, resultando em uma exceção se await for usado.

Para evitar abusos, essa solicitação do navegador só vai aparecer após uma interação do usuário. É por isso que requestStorageAccess() precisa ser chamado inicialmente de um manipulador de eventos ativado pelo usuário, em vez de imediatamente após o carregamento do iframe:

async function doClick() {

  // Only do this extra check if access hasn't already been given
  // based on the hasAccess variable.
  if (!hasAccess) {
    try {
      await document.requestStorageAccess();
      hasAccess = true; // Can assume this was true if requestStorageAccess() did not reject.
    } catch (err) {
      // Access was not granted.
      return;
    }
  }

  if (hasAccess) {
    // Use the cookies
  }
}

document.querySelector('#my-button').addEventListener('click', doClick);

Se você precisar usar o armazenamento local em vez de cookies, faça o seguinte:

let handle = null;

async function doClick() {
  if (!handle) {
    try {
      handle = await document.requestStorageAccess({localStorage: true});
    } catch (err) {
      // Access was not granted.
      return;
    }
  }

  // Use handle to access unpartitioned local storage.
  handle.localStorage.setItem('foo', 'bar');
}

document.querySelector('#my-button').addEventListener('click', doClick);

Solicitações de permissão

Quando o usuário clica no botão pela primeira vez, a solicitação do navegador aparece automaticamente na maioria dos casos, normalmente na barra de endereço. A captura de tela a seguir mostra um exemplo da solicitação do Chrome, mas outros navegadores têm uma interface semelhante:

Solicitação de permissão da API Storage Access do Chrome
Solicitação de permissão da API Storage Access do Chrome

O navegador pode pular a solicitação e fornecer a permissão automaticamente em determinadas circunstâncias:

  • Se a página e o iframe foram usados nos últimos 30 dias após aceitar a solicitação.
  • Se o iframe incorporado faz parte de um conjunto de sites relacionados.
  • Se o FedCM for usado como um sinal de confiança para acesso ao armazenamento.
  • No Firefox, a solicitação também é ignorada para sites conhecidos (aqueles com os quais você interagiu no nível superior) nas primeiras cinco tentativas.

Como alternativa, o método pode ser rejeitado automaticamente sem mostrar a solicitação em determinadas circunstâncias:

  • Se o usuário não tiver visitado e interagido com o site proprietário do iframe como um documento de nível superior, e não em um iframe. Isso significa que a API Storage Access só é útil para sites incorporados que os usuários já visitaram em um contexto primário.
  • Se o método requestStorageAccess() for chamado fora de um evento de interação do usuário sem a aprovação prévia do comando após uma interação.

Embora o usuário seja solicitado no uso inicial, as visitas subsequentes podem resolver requestStorageAccess() sem uma solicitação e sem a interação do usuário no Chrome e no Firefox. O Safari sempre exige uma interação do usuário.

Como o acesso a cookies e ao armazenamento pode ser concedido sem uma solicitação ou interação do usuário, muitas vezes é possível receber acesso a cookies ou armazenamento não particionados antes de uma interação do usuário em navegadores compatíveis (Chrome e Firefox) chamando requestStorageAccess() no carregamento da página. Isso pode permitir que você acesse cookies e armazenamento não particionados imediatamente e ofereça uma experiência mais completa, mesmo antes do usuário interagir com o iframe. Isso pode ser uma experiência melhor do que esperar a interação do usuário em algumas situações.

FedCM como indicador de confiança para SAA

O FedCM (gerenciamento de credenciais federadas) é uma abordagem que preserva a privacidade dos serviços de identidade federada (como "Fazer login com...") que não depende de cookies de terceiros ou redirecionamentos de navegação.

Quando um usuário faz login em uma parte confiável (RP, na sigla em inglês) que tem algum conteúdo incorporado de um provedor de identidade de terceiros (IdP, na sigla em inglês) com o FedCM, o conteúdo incorporado do IdP pode receber acesso de armazenamento automático aos próprios cookies de nível superior não particionados. Para ativar o acesso automático ao armazenamento com o FedCM, estas condições precisam ser atendidas:

  • A autenticação do FedCM (o estado de login do usuário) precisa estar ativa.
  • O RP ativou a permissão identity-credentials-get configurando, por exemplo:
<iframe src="https://idp.example" allow="identity-credentials-get"></iframe>

Por exemplo, um iframe idp.example é incorporado em rp.example. Quando o usuário faz login com o FedCM, o iframe idp.example pode solicitar acesso de armazenamento para os próprios cookies de nível superior.

O rp.example faz uma chamada de FedCM para fazer login do usuário com o provedor de identidade idp.example:

// The user will be asked to grant FedCM permission.
const cred = await navigator.credentials.get({
  identity: {
    providers: [{
      configURL: 'https://idp.example/fedcm.json',
      clientId: '123',
    }],
  },
});

Depois que o usuário faz login, o IdP pode chamar requestStorageAccess() no iframe idp.example, desde que o RP tenha permitido isso explicitamente com a política de permissões. A incorporação vai receber automaticamente acesso de armazenamento ao próprio cookie de nível superior, sem ativação do usuário ou necessidade de outro solicitação de permissão:

// Make this call within the embedded IdP iframe:

// No user gesture is needed, and the storage access will be auto-granted.
await document.requestStorageAccess();

// This returns `true`.
const hasAccess = await document.hasStorageAccess();

A permissão só será concedida automaticamente enquanto o usuário estiver conectado com o FedCM. Quando a autenticação está inativa, os requisitos padrão do SAA se aplicam para conceder acesso ao armazenamento.

Usar a consulta de permissão storage-access

Para verificar se o acesso pode ser concedido sem uma interação do usuário, verifique o status da permissão storage-access e faça a chamada requestStoreAccess() antecipadamente apenas se nenhuma ação do usuário for necessária, em vez de fazer a chamada e ter falha quando uma interação for necessária.

Isso também permite que você gerencie a necessidade de uma solicitação antecipada exibindo conteúdo diferente, por exemplo, um botão de login.

O código a seguir adiciona a verificação de permissão storage-access ao exemplo anterior:

// Set a hasAccess boolean variable which defaults to false except for
// browsers which don't support the API - where we assume
// such browsers also don't block third-party cookies.
let hasAccess = false;

async function hasCookieAccess() {
  // Check if Storage Access API is supported
  if (!document.requestStorageAccess) {
    // Storage Access API is not supported so best we can do is
    // hope it's an older browser that doesn't block 3P cookies.
    return true;
  }

  // Check if access has already been granted
  if (await document.hasStorageAccess()) {
    return true;
  }

  // Check the storage-access permission
  // Wrap this in a try/catch for browsers that support the
  // Storage Access API but not this permission check
  // (e.g. Safari and earlier versions of Firefox).
  let permission;
  try {
    permission = await navigator.permissions.query(
      {name: 'storage-access'}
    );
  } catch (error) {
    // storage-access permission not supported. Assume no cookie access.
    return false;
  }

    if (permission) {
    if (permission.state === 'granted') {
      // Permission has previously been granted so can just call
      // requestStorageAccess() without a user interaction and
      // it will resolve automatically.
      try {
        await document.requestStorageAccess();
        return true;
      } catch (error) {
        // This shouldn't really fail if access is granted, but return false
        // if it does.
        return false;
      }
    } else if (permission.state === 'prompt') {
      // Need to call requestStorageAccess() after a user interaction
      // (potentially with a prompt). Can't do anything further here,
      // so handle this in the click handler.
      return false;
          } else if (permission.state === 'denied') {
            // Not used: see https://github.com/privacycg/storage-access/issues/149
      return false;
          }
    }

  // By default return false, though should really be caught by earlier tests.
  return false;
}

async function handleCookieAccessInit() {
  hasAccess = await hasCookieAccess();

  if (hasAccess) {
    // Use the cookies.
  }
}

handleCookieAccessInit();

Iframes no modo sandbox

Ao usar a API Storage Access em iframes no modo sandbox, as seguintes permissões são necessárias:

  • O allow-storage-access-by-user-activation é necessário para permitir o acesso à API Storage Access.
  • O allow-scripts é necessário para permitir que o JavaScript chame a API.
  • O allow-same-origin é necessário para permitir o acesso a cookies de mesma origem e a outros armazenamentos.

Exemplo:

<iframe sandbox="allow-storage-access-by-user-activation
                 allow-scripts
                 allow-same-origin"
        src="..."></iframe>

Para serem acessados com a API Storage Access no Chrome, os cookies entre sites precisam ser definidos com os dois atributos a seguir:

  • SameSite=None, que é necessário para marcar o cookie como "cross-site".
  • Secure: garante que apenas os cookies definidos por sites HTTPS possam ser acessados.

No Firefox e no Safari, os cookies são definidos como SameSite=None por padrão e não restringem o SAA a cookies Secure. Portanto, esses atributos não são necessários. É recomendável ser explícito sobre o atributo SameSite e sempre usar cookies Secure.

Acesso à página de nível superior

A API Storage Access tem como objetivo permitir o acesso a cookies de terceiros em iframes incorporados.

Há também outros casos de uso em que a página de nível superior exige acesso a cookies de terceiros. Por exemplo, imagens ou scripts restritos por cookies, que os proprietários de sites podem querer incluir diretamente no documento de nível superior, em vez de em um iframe. Para resolver esse caso de uso, o Chrome propôs uma extensão da API Storage Access, que adiciona um método requestStorageAccessFor().

O método requestStorageAccessFor()

Compatibilidade com navegadores

  • Chrome: 119.
  • Edge: 119.
  • Firefox: não é compatível.
  • Safari: não é compatível.

Origem

O método requestStorageAccessFor() funciona de maneira semelhante ao requestStorageAccess(), mas para recursos de nível superior. Ele só pode ser usado para sites em um conjunto de sites relacionados para evitar o acesso geral a cookies de terceiros.

Para mais detalhes sobre como usar requestStorageAccessFor(), leia o Guia para desenvolvedores sobre conjuntos de sites relacionados.

A consulta de permissão top-level-storage-access

Compatibilidade com navegadores

  • Chrome: não é compatível.
  • Edge: não é compatível.
  • Firefox: não é compatível.
  • Safari: não é compatível.

Assim como a permissão storage-access, há uma permissão top-level-storage-access para verificar se o acesso pode ser concedido para requestStorageAccessFor().

Qual é a diferença entre a API Storage Access quando usada com o RWS?

Quando os conjuntos de sites relacionados são usados com a API Storage Access, alguns recursos adicionais ficam disponíveis, conforme detalhado na tabela a seguir:

Sem RWS Com RWS
Requer um gesto do usuário para iniciar a solicitação de acesso ao armazenamento
O usuário precisa acessar a origem de armazenamento solicitada em um contexto de nível superior antes de conceder acesso.
A solicitação para o primeiro usuário pode ser pulada
requestStorageAccess não precisa ser chamado se o acesso já tiver sido concedido
Concede acesso automático a outros domínios em um site relacionado
Suporte a requestStorageAccessFor para acesso a páginas de nível superior
Diferenças entre o uso da API Storage Access com e sem conjuntos de sites relacionados

Demonstração: como definir e acessar cookies

A demonstração a seguir mostra como um cookie definido por você na primeira tela da demonstração pode ser acessado em um frame incorporado no segundo site da demonstração:

storage-access-api-demo.glitch.me

A demonstração exige um navegador com cookies de terceiros desativados:

  • Chrome 118 ou mais recente com a flag chrome://flags/#test-third-party-cookie-phaseout definida e o navegador reiniciado.
  • Firefox
  • Safari

Demonstração: como configurar o armazenamento local

A demonstração a seguir mostra como acessar canais de transmissão não particionados de um iframe de terceiros usando a API Storage Access:

https://saa-beyond-cookies.glitch.me/

A demonstração exige o Chrome 125 ou mais recente com a flag test-third-party-cookie-phaseout ativada.

Recursos