Skip to content
View lessons Login
3d cartoon hands holding a phone

Unlock full course by purchasing a membership

Understanding and Implementing Firestore Security Rules

Understanding and Implementing Firestore Security Rules

So far, we have just been interacting with Firestore using the test security rules. This basically lets us do whatever we want. Notice that we have been adding messages to our database without having to login or authenticate in any way. If we launch this application as is, it means absolutely anybody can read/write the data in our database.

It’s not enough to just make restrictions inside of our application either. Let’s say we didn’t have an interface in the application for adding a message

  • it would still be possible for people to connect to our database and read/write as they please. If the security rules allow it, it can be done. We need to make sure our security rules describe exactly what can and can not be done and by whom.

These rules can be found in the Rules tab which is next to the Data tab inside of your Firestore database (accessed through your project in the Firebase console). But, we will generally be using the firestore.rules file inside of our project to manage our rules and deploy them with:

Terminal window
firebase deploy

The set of rules which we have currently (since we are in test mode) looks like this:

rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// This rule allows anyone with your Firestore database reference to view, edit,
// and delete all data in your Firestore database. It is useful for getting
// started, but it is configured to expire after 30 days because it
// leaves your app open to attackers. At that time, all client
// requests to your Firestore database will be denied.
//
// Make sure to write security rules for your app before that time, or else
// all client requests to your Firestore database will be denied until you Update
// your rules
match /{document=**} {
allow read, write: if request.time < timestamp.date(2023, 11, 25);
}
}
}

This setup means that all reads and writes will be allowed to the database, no matter who is making them. If you wanted to change these rules, you would need to make modifications to them here and publish the new rules (again, either through the Firebase console or locally and by running firebase deploy).

In this lesson, we are going to go on a bit of a journey from creating basic security rules to the final security rules that our application will require in order to be secured to the level that we need. Along the way, this will allow us to explain various aspects of how Firestore Security Rules work.

We won’t be covering every aspect of Firestore Security Rules, there is just too much to learn, but this should give you a solid grounding for how creating security rules works in general. The exact kinds of rules you need to write will depend on the specifics of the application you are creating.

Despite my warning, please do attempt to learn and have fun with security in the right environment. Even if it may take a while to learn enough to start handling all security concerns yourself, knowing a little bit can provide you with a lot of insight.

Match & Allow

Creating Firestore security rules mostly comes down to these two concepts: match and allow. We will use match to target a specific collection or document, and we will use allow to define an expression to determine how that specific collection/document may be accessed.

When writing our match statements, there is a bit of boilerplate code that mostly won’t change. For example, the default rules for a “locked” database (the opposite of our “test mode” database) look like this:

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

This might look a bit intimidating, but we can mostly forget about all of this:

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

This code just means that we are targeting the firestore service, and the first match statement just means we are targeting the default database in our project — we won’t need to change this. All of the important stuff will be inside of this initial match, e.g:

match /{document=**} {
allow read, write: if false;
}

This particular match uses the {document=**} recursive wildcard to target every document in the database, and in this case, it is blocking all reads and writes. You won’t typically just use a blanket match like this, but rather target specific documents or collections with your match statement, e.g:

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

In this case, we are attempting to match the messages collection. We use the {message} wildcard to match against any message in the collection, and then this will also make a message variable available to the allow expression we write (such that we could check the specifics of a document in our rule). You don’t have to use a wildcard, you could also just match a single specific document, but you can’t just match an entire collection by doing this: /messages/. If you want your security rules to apply to an entire collection, you must use a wildcard: /messages/{message}.

Although we are only matching one collection here, and this is all we will need for the application we are building, you can also match other collections or documents (or even sub-collections) and create different rules for those. For example, we might want to do something like this:

rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /messages/{message} {
allow read;
allow write: if false;
}
match /posts/{post} {
allow read;
allow write: if false;
match /comments/{comment} {
allow read;
allow create: if true;
allow update, delete: if false;
}
}
}
}
EXTENDED EXTENDED

Thanks for checking out the preview of this lesson!

You do not have the appropriate membership to view the full lesson. If you would like full access to this module you can view membership options (or log in if you are already have an appropriate membership).