loading...

Firestore Rules Examples – Must-Know Patterns To Secure Your Data

jamal_moir profile image Jamal Moir ・4 min read

This post is part of a post originally posted on my blog where I write about coding, software development and developer productivity.


I've been there… You’re staring at a blank firestore.rules page, not knowing where to start. You want to make sure that your website is secure, but you’re not sure what to do and you are worried that you will do it incorrectly. But have no fear! These Firestore rules examples will give you the base that you need to safely secure your website or application.

Firestore rules are actually fairly simple and follow a logical structure. The examples below go over common situations that might arise in your app, and how to write rules to make sure that your data is safe! Learn these patterns and you will be able to whip up a secured database in no time at all.


Firestore Rules Examples

  1. Denying All Reads
  2. Denying All Writes
  3. Checking if a User is Authenticated
  4. Checking if a Document Being Accessed Belongs to the Requesting User
  5. Checking if a Document Being Created Belongs to the Requesting User
  6. Using Functions **
  7. Verifying a Value’s Type **
  8. Verifying That a Value Belongs to a List of Values **
  9. Verifying a Values Length **
  10. Getting a Document From Another Collection **

**You can see examples 6-10 here


Denying All Reads

Sometimes you want to store data, but you just don’t want it to be accessed.

Maybe you have sensitive data that you want to persist, but that you don’t want to be accessible via your API. Maybe you didn’t follow the advice in this article and user data is leaking out into places it shouldn’t be and you need to turn off the tap quickly.

Either way there are many legitimate reasons for denying all reads to your database, and luckily, with Firestore rules it is very easy to do.

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read: if false;
    }
  }
}

Denying All Writes

Denying all writes is another thing that you might find yourself wanting to do. Maybe you have written a bunch of articles and manually added them to your Firestore database. You want to display them on your website, but want to make sure that no one can modify or delete them.

Similarly to the above denying all writes is trivial.

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow write: if false;
    }
  }
}

If you want deny both reading and writing to the database, then the two can be combined like so.

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if false;
    }
  }
}

Checking if a User is Authenticated

If you don’t want to deny all read and write access to your database, and want users to be able to see, create and change things on your website or app, then you are probably going to want them to be authenticated.

The following Firestore rule example does this by checking that the request being made to your database contains a uid.

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: request.auth.uid != null;
    }
  }
}

Checking if a Document Being Accessed Belongs to the Requesting User

Now, using the previous example we made sure that only authenticated users can access our data, but what about if we want to take this one step further?

Often we don’t want to just let all users access all data, but further separate it out, and only let users see their own documents.

To do this in Firestore, when creating documents you should create a userID field and store the creating user’s uid in it. Then, when trying to access that document later on, check to see if the uid in the request matches the user ID that is stored in the resource being accessed.

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /petowners/{ownerId} {
      request.auth.uid == resource.data.userId;
    }
  }
}

Checking if a Document Being Created Belongs to the Requesting User

In addition to only letting users see their own data, we only want to let them write data that belongs to their account. Letting users write to other peoples accounts could get us in all sorts of trouble!

This is done in a similar fashion to the example above. The only difference is that instead of checking the resource object’s user id, we check the request.resource object’s one.

The request.resource object is the document that is being sent in the request to your database.

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /petowners/{ownerId} {
      request.auth.uid == request.resource.data.userId;
    }
  }
}

Firestore is a great database to quickly get your apps up and running. Perfect for churning out all the website and app ideas that you have (if you struggle to come up with ideas, check this post out).

But, even for small side projects, if there is ever the chance that you will get users (yourself included!), then considering security from the outset is a must.

Hopefully these Firestore rules examples have shed a bit of light on how you can secure your database too.

Posted on by:

jamal_moir profile

Jamal Moir

@jamal_moir

Developer at a FinTech startup. Software should be beautiful inside and out. Python and JavaScript are my go-tos.

Discussion

markdown guide
 

Signed up to say thank you for this write up! I found it more straightforward than Google's own explanations. If you made a comprehensive list of functionality like a cheat sheet, I'm sure it would be a hit. I recently came across hasAll by digging into some stackoverflow thread. It would be great to have all the lesser-known abilities laid out somewhere.

 

Now, how about making a rule for an authenticcated user to read, write to his document together.