Does revoking read access in Realtime Database immediately disconnect active listeners?

Viewed 102

I'm trying to create a Firebase Realtime Database security ruleset that only grants read access to users with specific whitelisted UIDs (stored and matched elsewhere in the database).

Suppose these whitelisted users had running listeners actively receiving database events. If I were to dynamically remove their UID from the whitelist, would their listeners stop working?

1 Answers

Firebase handles this scenario gracefully. It tracks which nodes are read when a security rule is evaluated, and then reevaluated the rule if one of the nodes changes.

I verified this with the following rules:

"63595280": {
  "allowed": { ".read": true },
  "data": {
    ".read": "data.parent().child('allowed').child(auth.uid).exists()",
    ".write": true
  }
},

So someone is allowed to read the data node when their UID is in the allowed node.

The test script (also on https://jsbin.com/dixonoy/edit?js,console):

firebase.auth().signInAnonymously();
firebase.auth().onAuthStateChanged(function(user) {
  console.log(user ? 'user: '+user.uid : 'no user');
});

var ref = firebase.database().ref("63595280");

ref.child('allowed').on('value', function(snapshot) {
  console.log('allowed: '+JSON.stringify(snapshot.val()));
});


console.log("Adding a listener");
ref.child('data').on('value', function(snapshot) {
  console.log(snapshot.val());
}, function(error) {
  console.error('error: '+JSON.stringify(error));
});

setInterval(function() {
  ref.child('data').set(new Date().toString());
}, 10000)

The code that writes just sets the current date/time every 10 seconds.

And the output:

Adding a listener
allowed: {"m4yXaC9wmCdJXOiL2LDPEJDPoHw1":true,"uid":true}
Thu Aug 27 2020 15:54:52 GMT-0700 (Pacific Daylight Time)
Thu Aug 27 2020 15:55:02 GMT-0700 (Pacific Daylight Time)
Thu Aug 27 2020 15:55:12 GMT-0700 (Pacific Daylight Time)
Thu Aug 27 2020 15:55:22 GMT-0700 (Pacific Daylight Time)
error: {"code":"PERMISSION_DENIED"}
allowed: {"uid":true}

You see that the allowed nodes contains the UID initially, so the listener is attached successfully. It then prints a few of the values until I (in the Firebase console) remove the UID from allowed. You then see the PERMISSION_DENIED and the new value of allowed.

My original (wrong) hypothesis is left below...


Firebase checks the read permissions in security rules:

  • When a listener is attached.
  • When the authentication state of the client changes.

Since neither of these happens in your scenario, I'd expect it to not immediately reject the existing listener but only do so when it reconnects. But this is something you should be able to test pretty quickly, so I recommend giving it a try and reporting back here with your findings.

Related