DEV Community

nop33.eth
nop33.eth

Posted on • Originally published at iliascreates.com on

Rules are not filters: Fixing Firebase "Missing or insufficient permissions" error

While experimenting with Firebase and specifically Cloud Firestore I reached the point where I had to control who can read and write data to my collections. Since the application I am building is a client-side application only, the Firebase way to restrict access to it is through Firebase Authentication and Cloud Firestore Security Rules.

For the purposes of this blog post, let’s assume that I have 1 main collection called flats which includes a subcollection called items.

After reading through the documentation, testing some rules, updating my collections structure, I ended up with the following rules:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {

    match /flats/{flatId} {
      allow create: if request.auth != null;
      allow read, update, delete: if request.auth != null
                                  && request.auth.uid in resource.data.idsOfUsersWithAccess;

      match /items/{itemId} {
        allow create: if request.auth != null;
        allow read, update, delete: if request.auth != null
                                    && request.auth.uid in resource.data.idsOfFlatmatesThatShareThis;
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

What the above rules basically say is that any authenticated user (request.auth != null) is allowed to create a flat, but they are only allowed to read, update or delete a flat if their unique ID (request.auth.uid) is included in the flat’s property called idsOfUsersWithAccess.

Now, since the items collection is a subcollection of the flats one, I created a nested rule which extends the previous one (read more about rules for hierarchical data in the docs). The rule says that only authenticated users are allowed to create items but in order to read, update or delete an item the user’s unique ID needs to be included in the idsOfFlatmatesThatShareThis property of the flat.

For some reason however I could not fetch the items of the flat in my app and I was getting the following error:

Uncaught (in promise) FirebaseError: Missing or insufficient permissions.
Enter fullscreen mode Exit fullscreen mode

After quite a bit of digging into my code and the Firebase docs I found the problem. My code to fetch the items of a flat is the following:

firestore.collection('flats').doc(flat.id)
         .collection('items').get()
Enter fullscreen mode Exit fullscreen mode

My simple brain (I like to call him Brian) had this thought:

If the authenticated user queries all flat items, the result will surely only include the ones they have access too, based on the security rules that I created.

WRONG.

The documentation on writing conditions for Cloud Firestore Security Rules clearly says:

Rules are not filters. You cannot write a query for all the documents in a collection and expect Cloud Firestore to return only the documents that the current client has permission to access.

Oopsie!

The problem was not in my rules. It was in my query. Adding a where clause to match the rule fixed the problem and I could now load the intented items:

firestore.collection('flats').doc(flat.id)
         .collection('items')
         .where('idsOfFlatmatesThatShareThis', 'array-contains', state.user.id)
         .get()
Enter fullscreen mode Exit fullscreen mode

What did I learn?

To spend a bit more time reading the docs before diving into coding! Or at least skimming through all of them quickly ;)

PS: I would totally recommend the video series of Get to know Cloud Firestore on Youtube.

Heroku

Simplify your DevOps and maximize your time.

Since 2007, Heroku has been the go-to platform for developers as it monitors uptime, performance, and infrastructure concerns, allowing you to focus on writing code.

Learn More

Top comments (0)

Billboard image

Create up to 10 Postgres Databases on Neon's free plan.

If you're starting a new project, Neon has got your databases covered. No credit cards. No trials. No getting in your way.

Try Neon for Free →

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay