Práticas recomendadas para usar signInWithRedirect em navegadores que bloqueiam o acesso ao armazenamento de terceiros

Este documento descreve as práticas recomendadas para usar inícios de sessão de redirecionamento em navegadores que bloqueiam cookies de terceiros. Tem de seguir uma das opções indicadas aqui para que signInWithRedirect() funcione como previsto em ambientes de produção, em todos os navegadores.

Vista geral

Para tornar o fluxo de signInWithRedirect() transparente para si e para os seus utilizadores, o SDK JavaScript de autenticação do Firebase usa um iframe de origem cruzada que se liga ao domínio do Firebase Hosting da sua app. No entanto, este mecanismo não funciona com navegadores que bloqueiam o acesso ao armazenamento de terceiros.

Uma vez que pedir aos utilizadores para desativarem as funcionalidades de partição de armazenamento no navegador é raramente uma opção, deve, em alternativa, aplicar uma das seguintes opções de configuração à sua app, consoante os detalhes do seu exemplo de utilização.

  • Se alojar a sua app com o Firebase Hosting num subdomínio de firebaseapp.com, não é afetado por este problema e não tem de fazer nada.
  • Se alojar a sua app com o Firebase Hosting num domínio personalizado ou num subdomínio de web.app, use a Opção 1.
  • Se alojar a sua app com um serviço que não seja o Firebase, use a Opção 2, Opção 3, Opção 4, ou Opção 5.

Opção 1: atualize a configuração do Firebase para usar o seu domínio personalizado como authDomain

Se estiver a alojar a sua app com o Firebase Hosting através de um domínio personalizado, pode configurar o SDK do Firebase para usar o seu domínio personalizado como o authDomain. Isto garante que a sua app e o iFrame de autenticação usam o mesmo domínio, o que evita o problema de início de sessão. (Se não usar o Firebase Hosting, tem de usar uma opção diferente.) Certifique-se de que configurou o domínio personalizado no mesmo projeto que está a usar para a autenticação.

Para atualizar a configuração do Firebase de modo a usar o seu domínio personalizado como domínio de autenticação, faça o seguinte:

  1. Configure o SDK do Firebase JS para usar o seu domínio personalizado como authDomain:

    const firebaseConfig = {
      apiKey: "<api-key>",
      authDomain: "<the-domain-that-serves-your-app>",
      databaseURL: "<database-url>",
      projectId: "<project-id>",
      appId: "<app-id>"
    };
    
  1. Adicione o novo authDomain à lista de URIs de redirecionamento autorizados do seu fornecedor de OAuth. A forma como o faz depende do fornecedor, mas, em geral, pode seguir a secção "Antes de começar" em qualquer fornecedor para obter instruções exatas (por exemplo, o fornecedor do Facebook). O URI atualizado para autorizar tem o seguinte aspeto: https://<the-domain-that-serves-your-app>/__/auth/handler. O /__/auth/handler no final é importante.

    Da mesma forma, se estiver a usar um fornecedor SAML, adicione o novo authDomain ao URL do serviço de consumo de declarações SAML (ACS).

  2. Certifique-se de que o seu continue_uri está na lista de domínios autorizados.

  3. Volte a implementar com o Firebase Hosting, se necessário, para obter o ficheiro de configuração do Firebase mais atualizado alojado em /__/firebase/init.json.

Opção 2: mude para signInWithPopup()

Use signInWithPopup() em vez de signInWithRedirect(). O resto do código da sua app permanece igual, mas o objeto UserCredential é obtido de forma diferente.

Versão Web 9

  // Before
  // ==============
  signInWithRedirect(auth, new GoogleAuthProvider());
  // After the page redirects back
  const userCred = await getRedirectResult(auth);

  // After
  // ==============
  const userCred = await signInWithPopup(auth, new GoogleAuthProvider());

Versão Web 8

  // Before
  // ==============
  firebase.auth().signInWithRedirect(new firebase.auth.GoogleAuthProvider());
  // After the page redirects back
  var userCred = await firebase.auth().getRedirectResult();

  // After
  // ==============
  var userCred = await firebase.auth().signInWithPopup(
      new firebase.auth.GoogleAuthProvider());
```

O início de sessão através de pop-ups nem sempre é ideal para os utilizadores. Por vezes, os pop-ups são bloqueados pelo dispositivo ou pela plataforma, e o fluxo é menos fluido para os utilizadores de dispositivos móveis. Se a utilização de pop-ups for um problema para a sua app, tem de seguir uma das outras opções.

Opção 3: encaminhe pedidos de autorização para firebaseapp.com

O fluxo signInWithRedirect começa com um redirecionamento do domínio da sua app para o domínio especificado no parâmetro authDomain na configuração do Firebase (".firebaseapp.com" por predefinição). authDomain aloja o código do auxiliar de início de sessão que redireciona para o fornecedor de identidade que, em caso de êxito, redireciona de volta para o domínio da app.

Quando o fluxo de autenticação regressa ao domínio da sua app, é acedido o armazenamento do navegador do domínio do auxiliar de início de sessão. Esta opção e a seguinte (para alojar o código autonomamente) eliminam o acesso ao armazenamento de origem cruzada, que, de outra forma, é bloqueado pelos navegadores.

  1. Configure um proxy inverso no servidor da app para que os pedidos GET/POST para https://<app domain>/__/auth/ sejam encaminhados para https://<project>.firebaseapp.com/__/auth/. Certifique-se de que este encaminhamento é transparente para o navegador. Não é possível fazê-lo através de um redirecionamento 302.

    Se estiver a usar o nginx para publicar o seu domínio personalizado, a configuração do proxy inverso tem o seguinte aspeto:

    # reverse proxy for signin-helpers for popup/redirect sign in.
    location /__/auth {
      proxy_pass https://<project>.firebaseapp.com;
    }
    
  2. Siga os passos na Opção 1 para atualizar o redirect_uri autorizado, o URL do ACS e o seu authDomain. Depois de voltar a implementar a app, o acesso ao armazenamento de origem cruzada deve deixar de ocorrer.

Opção 4: aloje o código do auxiliar de início de sessão no seu domínio

Outra forma de eliminar o acesso ao armazenamento de origem cruzada é alojar autonomamente o código auxiliar de início de sessão do Firebase. No entanto, esta abordagem não funciona para o início de sessão da Apple nem para o SAML. Use esta opção apenas se a configuração do proxy inverso na opção 3 for inviável.

A alojamento do código auxiliar tem os seguintes passos:

  1. Transfira os ficheiros para alojamento a partir da localização <project>.firebaseapp.com executando os seguintes comandos:

    mkdir signin_helpers/ && cd signin_helpers
    wget https://<project>.firebaseapp.com/__/auth/handler
    wget https://<project>.firebaseapp.com/__/auth/handler.js
    wget https://<project>.firebaseapp.com/__/auth/experiments.js
    wget https://<project>.firebaseapp.com/__/auth/iframe
    wget https://<project>.firebaseapp.com/__/auth/iframe.js
    wget https://<project>.firebaseapp.com/__/firebase/init.json
    
  2. Aloje os ficheiros acima no domínio da sua app. Certifique-se de que o seu servidor Web consegue responder a https://<app domain>/__/auth/<filename> e https://<app domain>/__/firebase/init.json.

    Segue-se uma implementação de servidor de exemplo que transfere e aloja os ficheiros. Recomendamos que transfira e sincronize os ficheiros periodicamente para garantir que as correções de erros e as funcionalidades mais recentes são aplicadas.

  3. Siga os passos na Opção 1 para atualizar o redirect_uri autorizado e o seu authDomain. Depois de voltar a implementar a app, o acesso ao armazenamento de origem cruzada deve deixar de ocorrer.

Opção 5: processar o início de sessão do fornecedor de forma independente

O SDK Firebase Authentication fornece signInWithPopup() e signInWithRedirect() como métodos práticos para encapsular lógica complicada e evitar a necessidade de envolver outro SDK. Pode evitar usar qualquer um dos métodos iniciando sessão de forma independente no seu fornecedor e, em seguida, usando signInWithCredential() para trocar as credenciais do fornecedor por uma credencial da Firebase Authentication. Por exemplo, pode usar o SDK de início de sessão Google, código de amostra para obter uma credencial de conta Google e, em seguida, instanciar uma nova credencial Google, executando o seguinte código:

Versão Web 9

  // `googleUser` from the onsuccess Google Sign In callback.
  //  googUser = gapi.auth2.getAuthInstance().currentUser.get();
  const credential = GoogleAuthProvider.credential(googleUser.getAuthResponse().id_token);
  const result = await signInWithCredential(auth, credential);

Versão Web 8

  // `googleUser` from the onsuccess Google Sign In callback.
  const credential = firebase.auth.GoogleAuthProvider.credential(
      googleUser.getAuthResponse().id_token);
  const result = await firebase.auth().signInWithCredential(credential);

Depois de chamar signInWithCredential(), o resto da app funciona da mesma forma que antes.

Pode encontrar instruções para obter uma credencial da Apple aqui.