0

I'm having some trouble getting onDisconnect().remove() working with authentication/security rules. Basically what I have is this:

First, I log the user in with auth():

var rootRef = new Firebase(FIREBASE_URL + 'sites/' + FIREBASE_ROOT);
rootRef.auth(user.FIREBASE_TOKEN, loginCallback);

Then, my loginCallback registers the current user as active and ensure that the user reference is removed on disconnect:

var activeUsers = $firebase(rootRef.child('pages/' + pageId + '/users')).$asArray();
var rawUser = {
  id: user.id,
  displayName: user.displayName
};
activeUsers.$add(rawUser).then(function (userRef) {

  userRef.onDisconnect().remove();

});

My security rules for this particular section of my Firebase look like this:

{
  "rules": {
    "sites": {
      "$siteName": {
        "pages": {
          "$pageId": {
            "users": {
              // only users with firebase access can use this
              ".read": "auth.firebase_user === true"
              "$arrayId": {
                // users can only write their own data
                ".write": "auth.firebase_user === true && auth.id === newData.child('id').val()",
                ".validate": "newData.hasChildren(['id', 'displayName'])"
              }
            }
          }
        }
      }
    }
  }
}

With this security configuration and JS, when users disconnect their reference is not removed from Firebase. However, if I use these security rules instead:

{
  "rules": {
    "sites": {
      "$siteName": {
        "pages": {
          "$pageId": {
            "users": {
              // only users with firebase access can use this
              ".read": "auth.firebase_user === true",
              ".write": "true",
              "$arrayId": {
                // users can only write their own data
                //".write": "auth.firebase_user === true && auth.id === newData.child('id').val()",
                ".validate": "newData.hasChildren(['id', 'displayName'])"
              }
            }
          }
        }
      }
    }
  }
}

User references are properly removed on disconnect.

I've tried a number of different security rules and JS implementations but they all end up basically with this problem.

Does anyone know if there could potentially be an authentication problem here? Are the user's auth variables making it to Firebase in time to remove the user properly?

Some side notes: I'm using AngularFire and this is basically a presence implementation for viewing who else is looking at the current page.

kand
  • 2,268
  • 6
  • 31
  • 43
  • 1
    A helpful debugging tool here is to put a callback into your onDisconnect().remove(/* callback here */) method so you can capture the security error. – Kato Sep 12 '14 at 19:54

1 Answers1

0

Figured it out, looks like the security rules where messing with how I was accessing objects in Firebase. Modified my security rules to look like this instead:

{
  "rules": {
    "sites": {
      "$siteName": {
        "pages": {
          "$pageId": {
            "users": {
              ".read": "auth.firebase_user === true",
              ".write": "auth.firebase_user === true",
              "$arrayId": {
                ".validate": "newData.hasChildren(['id', 'displayName']) && newData.child('id').val() === auth.id"
              }
            }
          }
        }
      }
    }
  }
}

Now firebase users can read and write, but anything they write must match the validation rules.

kand
  • 2,268
  • 6
  • 31
  • 43