简体   繁体   中英

Firebase gives error on database listener when signing out

I managed to make an authentication functionality, where the user can use:

  1. sign up
  2. log in
  3. update / delete account
  4. sign out

Everything works good until I sign out. I use onSnapshot() for the update functionality So everytime the auth state changes i set the returned data in the component's state.

firebase_auth.auth().onAuthStateChanged(user => {

    if(user) {

     firebase.collection('users').doc(user.uid).onSnapshot(doc => {

      doc.exists && this.setState(prevState => ({ ...prevState, user_data: doc.data() }));      

     });

 } else this.setState(prevState => ({ ...prevState, user_data: null }));

});

signOut() {

 firebase.auth().signOut();

}

When i sign out the following error occurs:

Uncaught Error in onSnapshot: FirebaseError: Missing or insufficient permissions.

Here are my database rules. I use firebase cloud storage .

service cloud.firestore {    
  match /databases/{database}/documents {      
    match /users/{uid} {        
      allow read, write: if request.auth.uid == uid      
    }    
  }  
} 

And if i stop the onSnapshot listener , not even the log in will work.

firebase_auth.auth().onAuthStateChanged(user => {

    if(user) {

     const unsubscribe = firebase.collection('users').doc(user.uid).onSnapshot(doc => {

       doc.exists && this.setState(prevState => ({ ...prevState, user_data: doc.data() }));
     });

     unsubscribe();

 } else this.setState(prevState => ({ ...prevState, user_data: null }));

});

It seems your Firestore security rules requite that the user is authenticated to read certain data. For that reason, the listener(s) for that data get rejected when you sign the user out.

The solution to prevent the error message, is to remove the listeners yourself in your code before signing the user out. So keep the unsubscribe in a field in the object where you can reach it from signOut() , and then:

signOut() {
  unsubscribe();
  firebase.auth().signOut();
}

So the fix for this problem is:

firebase_auth.auth().onAuthStateChanged(user => {

  if(user) {

   const unsubscribe = firebase.collection('users').doc(user.uid).onSnapshot(doc => {

    doc.exists && this.setState(prevState => ({ ...prevState, user_data: doc.data() }));   

   });

   this.setState(prevState => ({ ...prevState, unsubscribe });

 } else this.setState(prevState => ({ ...prevState, user_data: null }));

});

I set the unsubscribe function in the state , and use it later in the sign out :

signOut() {
  this.state.unsubscribe();
  firebase.auth().signOut();
}

Thank you frank .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM