Search code examples
firebasegoogle-cloud-platformgoogle-cloud-firestoreangularfire2

Unable to base security rule condition on resource data in Firebase


I am attempting very simple thing and that is matching request.auth.uid to a field value in my transaction documents (like this resource.data.useruid) in Firebase security rule in order to get transactions of a particular logged in user. However, I don't get any documents while querying for them and get an error instead.

This is how the collection looks like - just one document there with useruid field.

enter image description here

The field's value is mapped to the users uid (screenshot taken in the Authentication -> Users tab.

enter image description here

And the rule looks like this

enter image description here

I should get the one document back but every time I query the documents with that user logged in (I am using angularfire2 for those purposes) I get Error: Missing or insufficient permissions.

If I modify the rule condition to return always true or if I only check for truthiness of request.auth.uid I get the query result alright. The funny thing though is that with resource.data involved - eg. checking for value of the amount field in the firebase rule - the condition is never met. I tried to write it like

allow read, write: if resource.data.amount == 3

and got the error again. Seems like I don't get the resource.data Map at all.

I feel like I am missing something obvious, although after reading the guides, it seems alright to me and I am already out of ideas. The debugging capabilities (or lack of) make the whole process very slow.

Could you please explain to me, why I don't get the resource.data Map in the firebase security rule or point me to a place where the problem might be?


Solution

  • You have most probably missed one specific point in the doc: your query fails "because it does not include the same constraints as your security rules". See https://firebase.google.com/docs/firestore/security/rules-query#secure_and_query_documents_based_on_authuid

    The following, with your security rules works perfectly:

    firebase.auth().signInWithEmailAndPassword("[email protected]", "xxxxx")
        .then(function (info) {
            db.collection("transactions").where("userid", "==", info.uid).get().then(function(querySnapshot) {
                querySnapshot.forEach(function(doc) {
                    console.log(doc.id, " => ", doc.data());
                });
            });
    
        });
    

    If you remove the where clause, you get the exact error you are getting