¿Cómo puedo detectar si un usuario ya inició sesión en Firebase?

102

Estoy usando la API del nodo de base de fuego en mis archivos javascript para el inicio de sesión de Google.

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

Esto funciona bien y el usuario puede iniciar sesión con sus credenciales de Google. Cuando el usuario visita la página nuevamente, la ventana emergente se abre nuevamente, pero como ya ha iniciado sesión, la ventana emergente se cierra sin requerir ninguna interacción por parte del usuario. ¿Hay alguna forma de comprobar si ya hay un usuario que inició sesión antes de que aparezca la ventana emergente?

Jophin Joseph
fuente

Respuestas:

113

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

Debe agregar un observador de cambio de estado de autenticación.

firebase.auth().onAuthStateChanged(function(user) {
  if (user) {
    // User is signed in.
  } else {
    // No user is signed in.
  }
});
bojeil
fuente
3
Esto es inconsistente para mí. stackoverflow.com/questions/39395158/…
Dan P.
2
Usando onAuthStateChanged, ¿hay alguna manera de saber si un usuario es nuevo?
Brennan
Sí, pero no a través onAuthStateChanged. Esto se agregó en 4.6.0: firebase.google.com/support/release-notes/js#4.6.0 Puede obtenerlo desde el método de inicio de sesión o desde currentUser.metadata(última hora de inicio de sesión y hora de creación) ...
bojeil
@bojeil Creo que hay una advertencia sobre este método. Puede poner este código en una página y se activará incluso cuando no esté en esa página. Se activa cuando el AuthState cambia. Si cambia en otras páginas, efectivamente hará que se active cuando no lo desee. Al menos, eso es lo que me está pasando en este momento.
thevengefulco
1
Esto detectará eventos de inicio de sesión en otras pestañas. Funciona según lo previsto. Firebase Auth propaga eventos de inicio de sesión en todas las ventanas.
bojeil
82

También puede comprobar si hay un usuario actual

var user = firebase.auth().currentUser;

if (user) {
  // User is signed in.
} else {
  // No user is signed in.
}
Daniel Passos
fuente
8
Esto me devuelve nulo incluso después de un inicio de sesión inmediato.
Aarmora
8
Eso es extraño, funciona para mí, tal vez el problema sea porque la autenticación es asincrónica y _ currentUser_ aún no se actualizó.
Daniel Passos
1
De los documentos: currentUser también puede ser nulo porque el objeto auth no ha terminado de inicializarse. Si usa un observador para realizar un seguimiento del estado de inicio de sesión del usuario, no es necesario que maneje este caso.
Cheshireoctopus
No puedes confiar en eso. Consulte los documentos oficiales: "Hay algunos casos en los que getCurrentUser devolverá un valor no nulo ..."
Andrew
Si obtiene un valor nulo, probablemente sea porque aún no se ha inicializado.
Arnaldo Capo
28

Es no es posible decir si un usuario va a ser firmada cuando se inicia una página de carga, hay un trabajo alrededor sin embargo.

Puede memorizar el último estado de autenticación en localStorage para conservarlo entre sesiones y entre pestañas.

Luego, cuando la página comience a cargarse, puede asumir con optimismo que el usuario volverá a iniciar sesión automáticamente y pospondrá el cuadro de diálogo hasta que pueda estar seguro (es decir, después de los onAuthStateChangedincendios). De lo contrario, si ellocalStorage clave está vacía, puede mostrar el cuadro de diálogo de inmediato.

El onAuthStateChangedevento de base de fuego se activará aproximadamente 2 segundos después de que se cargue una 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()
  }
})



Estoy usando esto con React y react-router . Puse el código anterior en el componentDidMountcomponente raíz de mi aplicación. Allí, en el render, tengo algunosPrivateRoutes

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

Y así es como se implementa mi PrivateRoute:

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}}}
    // />
QWERTY
fuente
¿Crees que podrías ayudarme con esto? Probé la redirección de inicio de sesión automático que tiene en la parte superior de su respuesta, y ahora parece que no puedo eliminarla. Limpié mi almacenamiento local por completo y todavía no puedo acceder a mi sitio de base de fuego sin cerrar sesión debido a los redireccionamientos constantes.
hego64
@ hego64 ¿Realmente ha cerrado sesión en su aplicación firebase? Esta solución no realiza el inicio de sesión. Solo permite omitir el formulario de inicio de sesión si el usuario no se registró en la sesión anterior. / EDITAR: ¿Estás en un ciclo de redireccionamiento? Actualizaré la respuesta.
Qwerty
Sí, debería haber sido más claro, estaba atrapado en un bucle de redireccionamiento. Me desconectaba y, en lugar de volver a la aplicación, me llevaban directamente a la página de inicio de sesión. Pude solucionarlo volviendo a una implementación anterior, pero aparte de eso, no estaba seguro de qué hacer para solucionar el problema.
hego64
1
@ hego64 Los usuarios que no han iniciado sesión no deberían poder caminar libremente de todos modos, por lo que la redirección a la página de inicio de sesión es correcta, pero si hay rutas que están disponibles sin autenticación, entonces debe mover la lógica al enrutador o rutas particulares en su lugar, al igual que en mi ejemplo de contenedor PrivateRoute. Entonces, si el usuario está en una página restringida y cierra la sesión, será redirigido a la página de inicio de sesión. Tus otras rutas no tendrán esta lógica implementada.
Qwerty
Estuve atascado en esto por un tiempo ... este método funciona bastante bien. Gracias.
spetz83
17

No es necesario utilizar la función onAuthStateChanged () en este escenario.

Puede detectar fácilmente si el usuario está registrado o no ejecutando:

var user = firebase.auth().currentUser;

Para aquellos que enfrentan el problema de "devolver nulo", es solo porque no está esperando a que se complete la llamada a la base de fuego.

Supongamos que realiza la acción de inicio de sesión en la página A y luego invoca la página B, en la página B puede llamar al siguiente código JS para probar el comportamiento 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);
    });

Si el usuario está registrado, "var user" contendrá la carga útil JSON esperada; de lo contrario, será simplemente "nulo".

Y eso es todo lo que necesitas.

Saludos

Daniel Vukasovich
fuente
3
@Mauricio Silvestre ¿verdad? El uso firebase.auth.currentUserdevuelve indefinido independientemente de que haya
iniciado sesión
5

Otra forma es usar lo mismo que usa firebase.

Por ejemplo, cuando el usuario inicia sesión, firebase almacena los siguientes detalles en el almacenamiento local. Cuando el usuario vuelve a la página, firebase usa el mismo método para identificar si el usuario debe iniciar sesión automáticamente.

ingrese la descripción de la imagen aquí

ATTN: Como esto no está listado ni recomendado por firebase. Puede llamar a este método una forma no oficial de hacer esto. Lo que significa que más adelante, si firebase cambia su funcionamiento interno, es posible que este método no funcione. O en resumen. ¡Úselo bajo su propio riesgo! :)

ravish.hacker
fuente
5

Esto 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
  }
}
Ben Winding
fuente
1

Si está permitiendo usuarios anónimos, así como aquellos que iniciaron sesión con correo electrónico, puede usar firebase.auth().currentUser.isAnonymous, que devolverá trueo false.

maudulus
fuente
-3

Primero importe lo siguiente

import Firebase
import FirebaseAuth

Luego

    // Check if logged in
    if (Auth.auth().currentUser != null) {
      // User is logged in   
    }else{
      // User is not logged in
    }
Daniel
fuente