After logging in, I subscribe to some firebase refs, and then subsequently logout (FirebaseAuth.logout). Once I logout, I get a Firebase warning in the console: "Exception was thrown by user callback. Error: permission_denied at ...." and this becomes an actual exception. While I do expect to see this behavior, what are the best practices for logging a user out so I don't see this warning/exception?
-
This is a good question and it's unfortunate that no one has provided any insight. – MK_Dev Oct 24 '16 at 23:23
2 Answers
I had the same problem. Through the following source, I found a solution so far, wherewith I am not satisfied with yet. Source 1
The problem underlies in the fact, that there is still an open, not unsubscribed, subscription (connection to Firebase) somewhere in your code.
For example I did
this.name_sub = this.af.database.object("/users/" + user.uid + "/name")
.subscribe(data => {
this.globals.user.name = data.$value;
}
);
Which is totally fine, until the point you are invoking this.af.auth.logout();
. If you got your Firebase Security settings right, Firebase will throw an error, because you are not logged in with the user anymore - you are now anonymous, who should be blocked inside a user space. And because the above subscription is still active, Firebase tells you, that you do not have access with anonymous to the targeted user space.
Therefore, subscriptions must be closed. A way you could do this is, is adding
ngOnDestroy(){
this.name_sub.unsubscribe();
}
somewhere in your component. This would close your subscription when your component is destroyed. Unfortunately this is not possible for me, because I am doing the logout in another component. The way I am doing it now is closing the subscription, right after receiving a value.
this.name_sub = this.af.database.object("/users/" + user.uid + "/name")
.subscribe(data => {
this.globals.user.name = data.$value;
this.name_sub.unsubscribe(); // <-- important part
}
);
For me, this is super counter-intuitive. I think we need a way to receive value(s) without permanent subscribing to the data channel and without importing additional modules.
-
This is the correct answer; all subscriptions need to be unsubscribed from before logging out. Generally this is done in ngOnDestroy as pointed out by Niklas, and is best practice anyway to avoid memory leaks – Max Mumford Dec 23 '16 at 13:27
-
is there a way to unsubscribe everything before logging out? i just find it very tedious to find all the subscriptions and it is also very easy to forget in the future. – alltej Aug 31 '17 at 17:28
It's ugly, but works:
signOut(): void {
this.router.navigate(['/app').then(() => {
firebase.database().goOffline() // <=== this eliminates error!
this.afAuth.auth.signOut()
})
}