Search code examples
firebasegoogle-cloud-firestorefirebase-security

Firestore security rule - {wildcard} is neither null or not null when getting collection


I have set up a read rule on my firestore, and it works fine when doing a get on a single document by id, but fails with a FirebaseError: Missing or insufficient permissions. error when getting the collection.

It seems that it is the wildcard in the path that does not bind correctly when querying the collection. I have boiled down to a minimal example, which I logically don't think should fail the permission, but it does. It is as follows:

Data (formatted, but of course orrganized in collection/domument):

"items": {                   // collection "items"
   "item1" : {               // document "item1"
      "name": "first item"   // just dome dummy data
   }
}

the rules:

service cloud.firestore {
    match /databases/{database}/documents {
        match /items/{itemId} {
            allow read: if itemId != null;
        }
    }
}

The code (typescript) I use to access the database

// This line works fine, returns the document
firebase.firestore().collection("/items").doc("item1").get()

// This line gets a "FirebaseError: Missing or insufficient permissions." error
firebase.firestore().collection("/items").get()

I have tried changing the rule to

allow read: if itemId != null || itemId == null;

Which logically should be always true. However, the results are still the same, which lead me to believe there is some problems binding to the itemId wildcard.

Just as a sanity check, I also changed the rule to

allow read: if true;

And now both the get() on the collection and the document works fine (as expected), without any permission errors.

So am I missing something here, or is this a bug in firestore???


Solution

  • The rule you're proposing doesn't work because (as it is implemented currently), the wildcard variable has an undefined value for list (query) type requests (but not for get type requests, because the document ID is of course coming directly from the client). Queries might match multiple documents, and your query doesn't specify a document ID, so it can't be used in the rule.

    If you are ever expecting a rule to decide, on a per-document basis, whether or not it belongs in query results, that is also never going to work. This is because rules are not filters. All filters have to come from the client. If any of the documents that could possibly exist for the given filters would be rejected by the rule, then the entire request is rejected. (It is not scalable to actually check all the documents at the time of the requests - that could be incredibly slow).

    In other words, don't use the wildcard variable if you want to affect queries. Only use properties of the documents that could match, and make sure the client is specifying all of the relevant filters.