Comment détecter si un utilisateur est déjà connecté à Firebase?

103

J'utilise l'api du nœud Firebase dans mes fichiers javascript pour la connexion à Google.

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

Cela fonctionne bien et l'utilisateur peut se connecter avec ses informations d'identification Google. Lorsque l'utilisateur visite à nouveau la page, la fenêtre contextuelle s'ouvre à nouveau mais comme il s'est déjà connecté, la fenêtre contextuelle se ferme sans nécessiter d'interaction de la part de l'utilisateur. Existe-t-il un moyen de vérifier s'il y a déjà un utilisateur connecté avant d'afficher le popup?

Jophin Joseph
la source

Réponses:

113

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

Vous devez ajouter un observateur de changement d'état d'authentification.

firebase.auth().onAuthStateChanged(function(user) {
  if (user) {
    // User is signed in.
  } else {
    // No user is signed in.
  }
});
bojeil
la source
3
C'est incohérent pour moi. stackoverflow.com/questions/39395158/…
Dan P.
2
En utilisant onAuthStateChanged, existe-t-il un moyen de savoir si un utilisateur est nouveau?
Brennan
Oui, mais pas à travers onAuthStateChanged. Cela a été ajouté dans la version 4.6.0: firebase.google.com/support/release-notes/js#4.6.0 Vous pouvez l'obtenir à partir de la méthode de currentUser.metadataconnexion ou de (dernière connexion et heure de création) ...
bojeil
@bojeil Je pense qu'il y a une mise en garde à cette méthode. Vous pouvez mettre ce code sur une page et il se déclenchera même lorsque vous n'êtes pas sur cette page. Il se déclenche lorsque l'AuthState change. S'il change sur d'autres pages, vous le déclencherez effectivement lorsque vous ne le souhaitez pas. Du moins, c'est ce qui m'arrive en ce moment.
thevengefulco
1
Cela détectera les événements de connexion sur d'autres onglets. Cela fonctionne comme prévu. Firebase Auth propage les événements de connexion à travers les fenêtres.
bojeil
82

Vous pouvez également vérifier s'il existe un utilisateur actuel

var user = firebase.auth().currentUser;

if (user) {
  // User is signed in.
} else {
  // No user is signed in.
}
Daniel Passos
la source
8
Cela me renvoie nul même après une connexion immédiate.
Aarmora le
8
C'est étrange, cela fonctionne pour moi, peut-être que le problème vient du fait que auth est asynchrone et que _ currentUser_ n'a pas encore été mis à jour.
Daniel Passos
1
D'après la documentation: currentUser peut également être null car l'objet auth n'a pas terminé l'initialisation. Si vous utilisez un observateur pour suivre l'état de connexion de l'utilisateur, vous n'avez pas besoin de gérer ce cas.
cheshireoctopus
Vous ne pouvez pas vous y fier. Voir la documentation officielle: "Il y a des cas où getCurrentUser renverra un non-null ..."
Andrew
Si vous obtenez null, c'est probablement parce qu'il n'a pas encore été initialisé.
Arnaldo Capo
28

Il n'est pas possible de dire si un utilisateur sera signé lorsqu'une page commence à se charger, il y a cependant un contournement.

Vous pouvez mémoriser le dernier état d'authentification dans localStorage pour le conserver entre les sessions et entre les onglets.

Ensuite, lorsque la page commence à se charger, vous pouvez supposer avec optimisme que l'utilisateur se reconnectera automatiquement et reporter la boîte de dialogue jusqu'à ce que vous soyez sûr (c'est-à-dire après les onAuthStateChangedincendies). Sinon, si la localStorageclé est vide, vous pouvez afficher la boîte de dialogue immédiatement.

L' onAuthStateChangedévénement Firebase se déclenchera environ 2 secondes après le chargement d'une page.

// 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()
  }
})



J'utilise ceci avec React et react-router . J'ai mis le code ci-dessus dans componentDidMountmon composant racine d'application. Là, dans le rendu, j'en aiPrivateRoutes

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

Et voici comment ma PrivateRoute est implémentée:

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
la source
Pensez-vous que vous pourriez m'aider avec ça? J'ai essayé la redirection de connexion automatique que vous avez en haut de votre réponse, et maintenant je n'arrive pas à la supprimer. J'ai entièrement vidé mon stockage local et je ne peux toujours pas accéder à mon site Firebase déconnecté à cause des redirections constantes.
hego64
@ hego64 Vous êtes-vous déconnecté de votre application Firebase? Cette solution ne se connecte pas. Elle permet uniquement d'ignorer le formulaire de connexion si l'utilisateur ne s'est pas déconnecté lors de la session précédente. / EDIT: Êtes-vous dans une boucle de redirection? Je mettrai à jour la réponse.
Qwerty
Oui, j'aurais dû être plus clair, j'étais coincé dans une boucle de redirection. Je me déconnectais et au lieu de revenir à l'application, je suis retourné directement à la page de connexion. J'ai pu résoudre ce problème en revenant à un déploiement précédent, mais à part cela, je ne savais pas quoi faire pour résoudre le problème.
hego64
1
@ hego64 Les utilisateurs qui ne sont pas connectés ne devraient pas pouvoir se déplacer librement à tout moment, donc la redirection vers la page de connexion est correcte, mais s'il y a des routes disponibles sans authentification, vous devez alors déplacer la logique vers le routeur ou des routes particulières à la place, un peu comme dans mon exemple de wrapper PrivateRoute. Donc, si l'utilisateur est sur une page restreinte et se déconnecte, il sera alors redirigé vers la page de connexion. Vos autres itinéraires n'auront pas cette logique implémentée.
Qwerty
J'étais coincé là-dessus pendant un moment ... cette méthode fonctionne plutôt bien. Je vous remercie.
spetz83 le
17

Il n'est pas nécessaire d'utiliser la fonction onAuthStateChanged () dans ce scénario.

Vous pouvez facilement détecter si l'utilisateur est connecté ou non en exécutant:

var user = firebase.auth().currentUser;

Pour ceux qui sont confrontés au problème du "retour de null", c'est simplement parce que vous n'attendez pas que l'appel Firebase se termine.

Supposons que vous exécutiez l'action de connexion sur la page A, puis que vous invoquiez la page B, sur la page B, vous pouvez appeler le code JS suivant pour tester le comportement attendu:

  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 l'utilisateur est connecté, alors "var user" contiendra la charge utile JSON attendue, sinon, alors ce sera simplement "null"

Et c'est tout ce dont vous avez besoin.

Cordialement

Daniel Vukasovich
la source
3
@Mauricio Silvestre est-ce? L'utilisation firebase.auth.currentUserrenvoie indéfini si je suis connecté ou non. Seul auth () renvoie le résultat correct une fois connecté.
tsujp
5

Une autre manière est d'utiliser la même chose que celle utilisée par Firebase.

Par exemple, lorsque l'utilisateur se connecte, Firebase stocke les détails ci-dessous dans le stockage local. Lorsque l'utilisateur revient sur la page, Firebase utilise la même méthode pour identifier si l'utilisateur doit être connecté automatiquement.

entrez la description de l'image ici

ATTN: car cela n'est ni répertorié ni recommandé par Firebase. Vous pouvez appeler cette méthode une manière non officielle de faire cela. Ce qui signifie que plus tard, si Firebase modifie son fonctionnement interne, cette méthode peut ne pas fonctionner. Ou en bref. À utiliser à vos risques et périls! :)

ravish.hacker
la source
5

Cela marche:

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
la source
1

Si vous autorisez les utilisateurs anonymes ainsi que ceux connectés par e-mail, vous pouvez utiliser firebase.auth().currentUser.isAnonymous, qui renverra soit trueou false.

maudulus
la source
-3

Importez d'abord les éléments suivants

import Firebase
import FirebaseAuth

ensuite

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