2
votes

I'm new to Firebase and really struggling with the security rules.

I'm trying to store data for anonymous user sessions that can only be accessed by that user but as soon as I tighten up the security rules I get permission denied and can't work out why.

The structure I have is:

/userSessions/$user/user_id

The application pushes to user sessions and writes the user_id as returned by the anonymous login.

I have the following security rules:

{
  "rules": {
    ".read": true,
    "userSessions": {
      "$user": {
        ".write": "newData.child('user_id').val() == auth.id",
        "user_id": {
          ".validate": "newData.isString()"
        }
      }
    }
  }
}

I'm sure I'm doing something silly, but can't work out how to use the security simulator either so don't know how to go about troubleshooting this

Any help greatly appreciated

EDIT - Problem occurs when trying to create a new entry under userSessions after authenticating anonymously.

Code:

var userSessionsRef = new Firebase('https://xxxxxx.firebaseio.com/userSessions');
var userSession;
var auth = new FirebaseSimpleLogin( userSessionsRef, function(error,user) {
    if (error) {
        console.log(error);
    } else if (user) {
        userSessionsRef.child(user.id).set({
            user_id: user.id,
            provider: user.provider,
            created: Firebase.ServerValue.TIMESTAMP
            });
    userSession = new Firebase('https://xxxxx.firebaseio.com/userSessions/'+user.id);
    userSession.onDisconnect().remove();
}
1
What are you trying to do when you get permission denied?Andrew Lee
Create a new $user under userSessions - I'll update the questionJon Reeves
Hi @JonReeves! What do you get when you try this out in simulator? Also, it seems likely that user.id is a number (I assume you're using Twitter or Facebook? They both return numeric ids). Also, what data is getting set? Can you log the user object and post that here? There's a lot more data you can offer us that will make troubleshooting painless and quick.Kato
I can't actually use the simulator - it just says uh oh. Something went wrong...Jon Reeves
I am using anonymous authentication which returns a string for ID, and all I am setting at the moment is the data returned from the authentication and a timestamp (as in the code above) just to keep things simpleJon Reeves

1 Answers

2
votes

The set() operation you've provided runs great; no errors; there must be another issue at play here that you haven't captured in your repro (did you enable anonymous auth in Forge?). Here's a fiddle running on your security rules, copied line-for-line (just moved down one child path): http://jsfiddle.net/katowulf/wxn5J/

On a related note, your current security rules will not allow the userSession.onDisconnect().remove(); op, since records can only be written if newData() contains a user_id value (i.e. it can't be null). A better way to structure these security rules would be as follows:

{
  "rules": {
    ".read": true,
    "userSessions": {
      "$user": {
        ".write": "$user === auth.id", // delete allowed
        "user_id": {
          ".validate": "newData.isString() && newData.val() === $user"
        }
      }
    }
  }
}