1

I have the following Firebase rules, and I'm having trouble getting validation to work as expected:

{
  "rules": {
    ".read": true,
    ".write": true,

    "specialItems": {
      "$itemid": {
        ".validate": "root.child('items/' + $itemid).exists()"
      }
    }
  }
}

The intention of my .validate rule is that an entry in the 'specialItems' list is only accepted if it already exists in the 'items' list. Unfortunately Firebase is allowing me to add to specialItems regardless - no doubt because I misunderstand how validation should work.

I'm using the app engine python urlfetch API to talk to firebase via REST, and using the PATCH method.

auth_payload = {"uid": "custom:1", "auth_data": "foo"}
token = create_token(FIREBASE_SECRET, auth_payload, {"admin": True})

url = "https:/<my-app>.firebaseio.com/specialItems.json?auth=" + token
payload = json.dumps({"myItem": "ok"})

result = urlfetch.fetch(url=url, payload=payload, method=urlfetch.PATCH)

When starting with an empty database this leaves me with a complete data tree that looks like:

specialItems
  -- myItem: "ok"

I was expecting this tree to fail the validation rule. I've also tried using PUT, which has identical effect:

url = "https://<my-app>.firebaseio.com/specialItems/myItem.json?auth=" + token
result = urlfetch.fetch(url=url, payload='"ok"', method=urlfetch.PUT)

One other thing to note is that I currently need to authenticate with 'admin: True' in order to write anything, despite my rules seeming to indicate that anyone should have read/write access. Makes me wonder whether my rules are being applied at all - if that's the case, then I'm not sure how to enable my rules - they're right there in the 'Security & Rules' pane. I'm also assuming here that admin is not allowed to violate schema validation rules.

hawkett
  • 3,053
  • 5
  • 29
  • 39
  • You'll want to remove that `.write: true` on the root path right away. You've essentially given the world global write access to your repo. (hint: I can curl -x DELETE on your root path and you will have a sad day restoring from backup) – Kato Apr 24 '15 at 15:53
  • It's ok - I created a separate app specifically for this SO question. Deleting it now that I'm sorted - thanks for the help. Worth noting that when creating a new firebase app, the default rules doc is : { "rules": { ".read": true, ".write": true } } ;) – hawkett Apr 24 '15 at 17:45

2 Answers2

3

You've assumed incorrectly. Authenticating with admin: true will bypass security rules. Thus, your .validate rule will not be applied in this case. There's nothing physically wrong with the .validate rule itself.

Also, assuming your question accurately reflects the actual scenario, authentication is not necessary here. the .write/.read true on the root path will allow access to any data in your Firebase. In all likelihood, your rule is working quite well and preventing write, which is why you have falsely assumed you need admin: true in order to write the data.

Do check out the simulator as Saeed already suggested in his answer.

Kato
  • 40,352
  • 6
  • 119
  • 149
  • Simulator did show this up - thanks (will accept Saeed's ans.). Things that led me astray - a) docs: 'A .validate rule is used once a .write rule has granted access, to ensure that the data being written conforms to a specific standard.', b) firebase.com/docs/security/guide/securing-data.html#section-types : .validation doesn't read as auth c) admin:True docs: 'This method will grant a server complete read and write access' d) not expecting 'Permission Denied' for validation fail. No excuses, just the chain that led me to assume validation was not security but structural constraints. – hawkett Apr 24 '15 at 17:30
  • Regardless of current state, it would make a lot of sense to have an admin mode that wasn't allowed to violate .validation rules. – hawkett Apr 24 '15 at 17:41
  • Actually - the solution to this is fairly straight forward in the existing system - I just set the .write & .read rule at the root for a user called 'superuser' - i.e full read/write but validation is still applied. – hawkett Apr 24 '15 at 18:13
2

Try the following code

{
  "rules": {
    ".read": true,
    ".write": true,

    "specialItems": {
      "$itemid": {
        ".validate": "root.child('items').hasChild($itemid)"
      }
    }
  }
}

You can use the simulator on the dashboard to test your rules. Make sure you have checked 'Enable Anonymous User Authentication' if authentications is not required, authenticate, and then enter your url and check for read and write results.

Saeed D.
  • 1,125
  • 1
  • 11
  • 23