How To Secure Your Firebase Database with Database Rules

Cloud Firestore Firebase Database

Firebase is a fast-growing mobile application development suite. When compared to other popular services like Google App Engine, Netlify, and Heroku, Firebase ranks at the top in developer updates in the Platform-as-a-Service space.


But what exactly is Firebase? Why does security matter? And what can you do to prevent future security breaches that can potentially cost your data and money?


These are the questions we are going to answer today in this article:

What is Firebase?

Firebase, at its basic, is Google’s mobile application platform that provides you with all the necessary services that allow you to quickly boot up your application. It comes ready with a set of ready-to-integrate services such as authentication management, hosting, cloud functions for a scalable and microservice styled backend, cloud storage,  and most importantly — the real-time tableless database. The perks of Firebase as a service is that it cuts down the infrastructure setup and maintenance required when running a fullstack application.


At the heart of every application is data. Firebase actually has two database services — one is called Firebase Realtime database, and the newer and much better database is called Cloud Firestore. Since 2017, Google has been pushing Cloud Firestore as the main database service in the Firebase suite, and this is what we will be focusing on in this piece.


Why Security Matters in Cloud Firestore

It’s easy for developers to become complacent towards security, especially when applications are pushed into the production space. During the development phase, it’s easy to open all the security protocols for easier and faster application testing. It is also easy to forget to close up all the security protocols once we are done.


When we first start up a Cloud Firestore database in Firebase, the security protocols are at their strictest. This means that only approved applications are given the various read, write, validate, and indexOn capabilities. However, when we first start off with a barebones application, we often don’t have all the various security protocols set up within our apps to satisfy the access requirements.


It is also good to note that a lot of Firebase tutorials and guides start off by requiring the developer to turn off all the security protocols. However, they never really go into how to close the accessibility rules properly — let alone show you how to configure security policies for different accessibility levels.


Having multiple policies for different scenarios and access permissions allow you to fine-tune who has access to specific collections of data, and what they can do with it. This is the easiest way to prevent security and data breaches while equipping the developer with the ability to track and trace vulnerabilities based on accessibility levels.


So how do we write these accessibility policies? Read on in the next section to find out.


Securing Your Cloud Firestore Database with Database Rules

When you first create your Firestore Database, you will encounter the security policy rules settings. It looks something like this:


Cloud Firestore default security policy


n most tutorials and guides, they will tell you to select Start in test mode and hardly touch on security again. When you switch to test mode, the rule changes from allow read, write: if false; to enabling write capabilities on the condition that it is after the time you’ve booted up your database.


So the Cloud Firestore policy configuration code looks something like this:



To update your Cloud Firestore security policy, click on Firebase Database on your Firebase’ navigation panel, click on the Rules tab inside your database console and select Edit rules in order to change your accessibility and security policy.


Editing Cloud Firestore database security policy


While this first part of securing your Cloud Firestore database is simple enough, how do you actually write a security policy that adequately protects your data?


The general syntax for a Cloud Firestore security policy is as follows:



So, for example, if we wanted our entire database to be read only, the rule would look something like this:



However, if we want to grant write permissions to only authenticated users, you can use request.auth as a conditional parameter. So your policy may end up looking something like this:



What if you only want read permissions for a specific type of collection?

In the examples above, match / {document=**} acts as a blanket application to the entire database where {document=**} is the wildcard.


Let’s pretend that we are working on an education-based database that deals with courses and their individual classes for the entire semester. This means we may have a collection called courses and inside this collection are individual documents called courseMaterials.


To fine tune our policy to read only access for authenticated users would look something like this:



A read rule can also be broken into get and list, while a write rule is broken into create, update, and delete.

So if we decide that only authenticated users can read, and update but not delete data, then the policy will look something like this:



But when you use request.auth != null, it means that anyone can perform the read and write operations.

A common pattern is to allow only authenticated users to read and write their own data. To do this, you track the auth.uid against the incoming userId. You can also use chaining to group rules together.


So your policy can end up looking like this:



Let’s pretend that some course materials are available without restrictions. To allow read access to this, you’ll need another data point that’s set to true. Continuing on our courses example, this may be achieved through a visibility data setting on our documents.


So your policy may end up looking something like this:



If you have more than a single collection that you want to target, you can nest your policies inside match /databases/{database}/documents {}. So you Cloud Firestore policy can end up looking something like this:



The create rule under match /cohorts/{students} is an example of giving only authenticated users with admin roles permissions to create or delete a student from the database.


While on the surface, these Cloud Firestore security rules look a bit like data filters — they are not. This is because the role of these rules only extends to protect accessibility to data only if the permissions levels are satisfied. For example, if your role data is incorrect, your security rules will not know the difference.


In Conclusion

Securing your Cloud Firestore database is not hard. However, many of us do not do it as we develop our applications, leaving potential holes that are caused by relying on your default settings.


The best practice is to start your database off in its strictest mode and slowly relax the rules based on the required permissions and accessibility levels. This will ensure that you are developing your apps with a security-first approach rather than it being an afterthought.


Aphinya Dechalert

Aphinya Dechalert / About Author

Aphinya is a skilled technical writer with field experiences in software development, agile, and JavaScript full stack with AWS and Google cloud. She is a developer advocate and community builder, helping others navigate their journeys and careers as developers.