Como posso detectar se um usuário já está conectado ao Firebase?


102

Estou usando o Firebase node api em meus arquivos javascript para o login do Google.

firebase.initializeApp(config);
let provider = new firebase.auth.GoogleAuthProvider();
firebase.auth().signInWithPopup(provider);

Isso funciona bem e o usuário pode fazer login com suas credenciais do Google. Quando o usuário visita a página novamente, o pop-up é aberto novamente, mas como ele já fez login, o pop-up fecha sem exigir nenhuma interação do usuário. Existe alguma maneira de verificar se já existe um usuário conectado antes de abrir o pop-up?

Respostas:


113

https://firebase.google.com/docs/auth/web/manage-users

Você tem que adicionar um observador de mudança de estado de autenticação.

firebase.auth().onAuthStateChanged(function(user) {
  if (user) {
    // User is signed in.
  } else {
    // No user is signed in.
  }
});

3
Isso é inconsistente para mim. stackoverflow.com/questions/39395158/…
— Dan P.

2
Usando onAuthStateChanged, há uma maneira de saber se um usuário é novo?
— Brennan

Sim, mas não completamente onAuthStateChanged. Isso foi adicionado em 4.6.0: firebase.google.com/support/release-notes/js#4.6.0 Você pode obtê-lo no método de currentUser.metadatalogin ou em (hora do último login e hora de criação) ...
— bojeil

@bojeil Acho que há uma ressalva nesse método. Você pode colocar esse código em uma página e ele será acionado mesmo quando você não estiver nessa página. Ele é acionado quando o AuthState muda. Se mudar em outras páginas, você efetivamente fará com que seja acionado quando não quiser. Pelo menos, é isso que está acontecendo comigo agora.
— thevengefulco

1
Isso detectará eventos de login em outras guias. Funciona como pretendido. O Firebase Auth propaga eventos de login nas janelas.
— bojeil

82

Você também pode verificar se há um usuário atual

var user = firebase.auth().currentUser;

if (user) {
  // User is signed in.
} else {
  // No user is signed in.
}

8
Isso está retornando nulo para mim, mesmo após um login imediato.
— Aarmora

8
Isso é estranho, funciona para mim, talvez o problema seja porque auth é assíncrono e _ currentUser_ ainda não foi atualizado.
— Daniel Passos

1
Nos documentos: currentUser também pode ser nulo porque o objeto auth não concluiu a inicialização. Se você usar um observador para rastrear o status de login do usuário, não será necessário lidar com este caso.
— cheshireoctopus

Você não pode confiar nisso. Consulte a documentação oficial: "Existem alguns casos em que getCurrentUser retornará um valor não nulo ..."
— Andrew

Se você está obtendo nulo, provavelmente é porque ele ainda não foi inicializado.
— Arnaldo Capo

28

Não é possível dizer se um usuário será assinado quando uma página começar a carregar, no entanto, há uma solução alternativa.

Você pode memorizar o último estado de autenticação em localStorage para persisti-lo entre as sessões e entre as guias.

Então, quando a página começar a carregar, você pode assumir de forma otimista que o usuário fará login novamente automaticamente e adiar a caixa de diálogo até que você tenha certeza (ou seja, após os onAuthStateChangeddisparos). Caso contrário, se a localStoragechave estiver vazia, você pode mostrar a caixa de diálogo imediatamente.

O onAuthStateChangedevento firebase será disparado cerca de 2 segundos após o carregamento de uma página.

// User signed out in previous session, show dialog immediately because there will be no auto-login
if (!localStorage.getItem('myPage.expectSignIn')) showDialog() // or redirect to sign-in page

firebase.auth().onAuthStateChanged(user => {
  if (user) {
    // User just signed in, we should not display dialog next time because of firebase auto-login
    localStorage.setItem('myPage.expectSignIn', '1')
  } else {
    // User just signed-out or auto-login failed, we will show sign-in form immediately the next time he loads the page
    localStorage.removeItem('myPage.expectSignIn')

    // Here implement logic to trigger the login dialog or redirect to sign-in page, if necessary. Don't redirect if dialog is already visible.
    // e.g. showDialog()
  }
})



Estou usando isso com React e react-router . Eu coloquei o código acima em componentDidMountmeu componente raiz do aplicativo. Lá, no render, eu tenho algunsPrivateRoutes

<Router>
  <Switch>
    <PrivateRoute
      exact path={routes.DASHBOARD}
      component={pages.Dashboard}
    />
...

E é assim que meu PrivateRoute é implementado:

export default function PrivateRoute(props) {
  return firebase.auth().currentUser != null
    ? <Route {...props}/>
    : localStorage.getItem('myPage.expectSignIn')
      // if user is expected to sign in automatically, display Spinner, otherwise redirect to login page.
      ? <Spinner centered size={400}/>
      : (
        <>
          Redirecting to sign in page.
          { location.replace(`/login?from=${props.path}`) }
        </>
      )
}

    // Using router Redirect instead of location.replace
    // <Redirect
    //   from={props.path}
    //   to={{pathname: routes.SIGN_IN, state: {from: props.path}}}
    // />

Você acha que poderia me ajudar com isso? Tentei o redirecionamento de login automático que você tem na parte superior da sua resposta e agora não consigo removê-lo. Limpei meu armazenamento local completamente e ainda não consigo acessar meu site do Firebase desconectado devido aos redirecionamentos constantes.
— hego64

@ hego64 Você realmente se desconectou do aplicativo Firebase? Esta solução não faz o login. Ela só permite pular o formulário de login se o usuário não se desconectar na sessão anterior. / EDIT: Você está em um loop de redirecionamento? Vou atualizar a resposta.
— Qwerty

Sim, eu deveria ter sido mais claro, estava preso em um loop de redirecionamento. Eu saía e, em vez de voltar para o aplicativo, era levado de volta para a página de login. Consegui consertar revertendo para uma implantação anterior, mas, fora isso, não tinha certeza do que fazer para corrigir o problema.
— hego64

1
@ hego64 Os usuários que não estão conectados não devem ser capazes de circular livremente de qualquer maneira, portanto, redirecionar para a página de login está correto, mas se houver rotas disponíveis sem autenticação, você deverá mover a lógica para o roteador ou rotas específicas, como em meu exemplo de wrapper PrivateRoute. Portanto, se o usuário estiver em uma página restrita e sair, ele será redirecionado para a página de login. Suas outras rotas não terão essa lógica implementada.
— Qwerty

Fiquei preso nisso por um tempo ... esse método funciona muito bem. Obrigado.
— spetz83

17

Não há necessidade de usar a função onAuthStateChanged () neste cenário.

Você pode detectar facilmente se o usuário está conectado ou não executando:

var user = firebase.auth().currentUser;

Para aqueles que enfrentam o problema de "retornar nulo", isso ocorre porque você não está esperando a conclusão da chamada do firebase.

Vamos supor que você execute a ação de login na página A e, em seguida, invoque a página B, na página B você pode chamar o seguinte código JS para testar o comportamento esperado:

  var config = {
    apiKey: "....",
    authDomain: "...",
    databaseURL: "...",
    projectId: "..",
    storageBucket: "..",
    messagingSenderId: ".."
  };
  firebase.initializeApp(config);

    $( document ).ready(function() {
        console.log( "testing.." );
        var user = firebase.auth().currentUser;
        console.log(user);
    });

Se o usuário estiver logado, "var user" conterá a carga útil JSON esperada; caso contrário, será apenas "nulo"

E isso é tudo que você precisa.

Saudações


3
@Mauricio Silvestre não é? O uso de firebase.auth.currentUserretorna undefined
— estando eu conectado

5

Outra maneira é usar a mesma coisa que o firebase usa.

Por exemplo, quando o usuário faz login, o firebase armazena os detalhes abaixo no armazenamento local. Quando o usuário volta à página, o firebase usa o mesmo método para identificar se o usuário deve fazer login automaticamente.

insira a descrição da imagem aqui

ATTN: como isso não está listado nem recomendado pelo firebase. Você pode chamar esse método de maneira não oficial de fazer isso. O que significa que mais tarde, se o firebase alterar seu funcionamento interno, esse método pode não funcionar. Ou em resumo. Use por sua conta e risco! :)


5

Isso funciona:

async function IsLoggedIn(): Promise<boolean> {
  try {
    await new Promise((resolve, reject) =>
      app.auth().onAuthStateChanged(
        user => {
          if (user) {
            // User is signed in.
            resolve(user)
          } else {
            // No user is signed in.
            reject('no user logged in')
          }
        },
        // Prevent console error
        error => reject(error)
      )
    )
    return true
  } catch (error) {
    return false
  }
}

1

Se você estiver permitindo usuários anônimos, bem como aqueles conectados com e-mail, você pode usar firebase.auth().currentUser.isAnonymous, que retornará trueou false.



-3

Primeiro importe o seguinte

import Firebase
import FirebaseAuth

Então

    // Check if logged in
    if (Auth.auth().currentUser != null) {
      // User is logged in   
    }else{
      // User is not logged in
    }
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.