Question

I have a Firebase with a security config like this:

{
    "rules": {
        "serviceproviders": {
            ".read": "auth != null",
            ".write": "auth != null"
        },
        "bookings": {
            ".read": "auth != null",
            ".write": true,
            ".validate": "newData.hasChildren(['phone', 'time', 'date', 'apikey'])",
            "apikey": {
                // only allow valid apikey
                ".validate": "root.child('serviceproviders/' + newData.val()).exists()"
            }
        },
        "status": {
            ".read": "auth != null",
            ".write": true
        }
    }
}

The idea is that users can only post /bookings/ with a valid apikey, that is, an apikey that can be found in /serviceproviders/.

In the Firebase simulator, this works as expected. However, when I use curl from the terminal, or Javascript from a html page, I get error: permission denied back from Firebase. I send exactly the same data (copy & paste).

My curl command looks like this:

$ curl -X POST -d '{"phone":"004512345678", "date":"2014-07-31","time":"10:00","apikey":"AA227D80-122C-4E5D-AEDF-24A829FA6403"}'  https://example.firebaseIO.com/bookings/.json

And I get back:

{
  "error" : "Permission denied"
}
Was it helpful?

Solution

OK, so after many hours of pulling my hair, I realized that in the guide on Firebase.com, the ".validate" rules are inside a block denoting the ID under that path, thus:

{
    "rules": {
        "serviceproviders": {
            ".read": "auth != null",
            ".write": "auth != null"
        },
        "bookings": {
            ".read": "auth != null",
            ".write": true,
            "$bookings_id": {
                "apikey": {
                    // only allow valid apikey
                    ".validate": "root.child('serviceproviders/' + newData.val()).exists()"
                },
                ".validate": "newData.hasChildren(['apikey','date','time','phone'])"
            }
        },
        "status": {
            ".read": "auth != null",
            ".write": true
        }
    }
}

works as expected, because of the "$bookings_id" block.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top