Reduzir o login de redirecionamento corrompido em navegadores que bloqueiam o acesso ao armazenamento de terceiros

Neste documento, explicamos como reduzir o login de redirecionamento corrompido em navegadores que bloqueiam cookies de terceiros.

Visão geral

Para simplificar o fluxo de signInWithRedirect() para desenvolvedores do Firebase e os usuários deles, o Firebase Authentication usa um iframe de origem cruzada que se conecta ao domínio do Firebase Hosting do seu app. No entanto, esse mecanismo não funciona com navegadores que bloqueiam o acesso ao armazenamento de terceiros.

Como pedir aos usuários para desativar os recursos de particionamento de armazenamento no navegador raramente é uma opção, implemente uma das seguintes mitigações no app, dependendo das especificações do caso de uso.

  • Se você hospeda o app com o Firebase Hosting em um subdomínio de firebaseapp.com, esse problema não tem efeito nenhum para você e não é preciso fazer nada.
  • Se você hospeda o app com o Firebase Hosting em um domínio personalizado (OU web.app), use a Mitigação nº 1.
  • Se você hospeda o app com outro serviço que não o Firebase, use a Mitigação nº 2, 3, 4 ou 5.

Mitigação nº 1: atualizar a configuração do Firebase para usar o domínio personalizado como authDomain

Se estiver hospedando seu aplicativo com o Firebase Hosting usando um domínio personalizado, configure o SDK do Firebase para usar seu domínio personalizado como authDomain. Isso garante que o app e o iframe de autenticação usem o mesmo domínio, o que impede o problema de login. Se você não usa o Firebase Hosting, é preciso usar uma mitigação diferente.

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

  1. Configure o SDK do Firebase para JavaScript para usar 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>"
    };
    
  2. Adicione o novo authDomain à lista de URIs de redirecionamento autorizados do provedor OAuth. O modo de fazer isso depende do provedor, mas, em geral, você pode seguir a seção "Antes de começar" em qualquer provedor para obter instruções exatas (por exemplo, o provedor do Facebook). O URI atualizado para autorização é semelhante a https://<the-domain-that-serves-your-app>/__/auth/handler. O /__/auth/handler final é importante.

Mitigação nº 2: alternar para signInWithPopup()

Use signInWithPopup() em vez de signInWithRedirect(). O restante do código do app continua o mesmo, mas a recuperação do objeto UserCredential é diferente.

Web version 9

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

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

Web version 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 login pop-up nem sempre é o ideal para usuários. Às vezes, os pop-ups são bloqueados pelo dispositivo ou plataforma, e o fluxo é menos estável para os usuários de dispositivos móveis. Se o uso de pop-ups for um problema para o app, siga uma das outras mitigações.

Mitigação nº 3: solicitações de autenticação de proxy para firebaseapp.com

O fluxo de signInWithRedirect começa redirecionando o domínio do app para o domínio especificado no parâmetro authDomain, na configuração do Firebase (".firebaseapp.com" por padrão). authDomain hospeda o código auxiliar de login que redireciona para o provedor de identidade, que, se não houver nenhum problema, redireciona para o domínio do app.

Quando o fluxo de autenticação retorna ao domínio do app, obtém-se acesso ao armazenamento do navegador do domínio auxiliar de login. Essa mitigação e a seguinte (para auto-hospedar o código) mitiga o acesso ao armazenamento de origem cruzada, que, de outra forma, é bloqueado pelos navegadores.

  1. Configure um proxy reverso no servidor do app para que as solicitações GET/POST para https://<app domain>/__/auth/ sejam encaminhadas para https://<project>.firebaseapp.com/__/auth/. Confirme se o encaminhamento é explícito para o navegador (isso não pode ser feito por meio de um redirecionamento 302).

    Se você usa o nginx para exibir seu domínio personalizado, a configuração de proxy reverso será como o exemplo abaixo:

    # reverse proxy for signin-helpers for popup/redirect sign in.
    location /__/auth {
      proxy_pass https://<project>.firebaseapp.com;
    }
    
  2. Siga as etapas da Mitigação 1 para atualizar o redirect_uri autorizado e authDomain. Depois de implantar novamente o app, não haverá mais o acesso ao armazenamento de origem cruzada.

Mitigação nº 4: auto-hospedar o código auxiliar de login no domínio

A hospedagem do código auxiliar divide-se nas etapas abaixo:

  1. Faça o download dos arquivos para hospedar do local <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
    
  2. Hospede os arquivos acima no domínio do app. Verifique se o servidor da Web pode responder a https://<app domain>/__/auth/<filename>.

    Veja um exemplo de implementação do servidor que faz o download e hospeda os arquivos.

  3. Siga as etapas da Mitigação 1 para atualizar o redirect_uri autorizado e authDomain. Depois de implantar novamente o app, não haverá mais o acesso ao armazenamento de origem cruzada.

Mitigação nº 5: gerenciar o login do provedor de maneira independente

O SDK do Firebase Authentication oferece signInWithPopup() e signInWithRedirect() como métodos práticos para encapsular a lógica complexa e evitar a necessidade de envolver outro SDK. Você pode evitar o uso de qualquer método. Para isso, faça login de maneira independente no seu provedor e, em seguida, use signInWithCredential() para trocar as credenciais do provedor por uma credencial do Firebase Authentication. Você pode usar, por exemplo, o SDK do Login do Google, o exemplo de código para receber uma credencial da Conta do Google e, em seguida, instanciar uma nova credencial do Google executando o seguinte código:

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

Web version 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 restante do app vai funcionar da mesma forma que antes.

Neste link, você encontra instruções sobre como receber uma credencial Apple.