Firestore and Security

Firestore is a game changer in databases! It’s never been this easy to save and query data without any hassle of setting up a server and database yourself. Everything is done client-side. But…

There is a security rule; never trust your client. Security should be handled by the server. But how is this done with Firestore?

If you’re not familiar with Firestore, check my past Medium article.

Introducing Firestore security rules. Which looks like this.

The some_path could match a single document using the document id. But often you would use the brackets {} for the document path, which matches any document in the collection.

Publish rules

They can be written and published in the rules tab in the Cloud Firestore section of the Firebase console or in a file in your project folder.

Deploy rules from your project folder

Make sure you have installed the Firebase CLI and are logged in.

Inside your project folder.

Which creates a .rules file you can edit your rules in. Then deploy them with this command.


If you only need your user to read data, you can put your entire database in read-only mode. Notice that these rules don’t apply to the admin sdk, so you could for example still write to the database using Firebase Functions.

We don’t need to specify false for write, because rules are secure by default.

Validating data

Let’s say users can’t post messages with a length longer than 160 characters and users can only read public messages. is used to require incoming data. While is the requested document fields.

One thing to keep in mind is that security rules are either accepted or denied. You can’t filter messages by adding the security rule for public messages. If a message could be private the entire read is denied. This logic only works with a where filter client side.

If you only had this logic client side, someone could alter your query from the developer tools and get the private messages.

Authenticated users

Firestore security rules integrate perfectly with Firebase Authentication. Which is trustworthy. Because when you sign in, Firebase will use a server-to-server call to the original identity provider which verifies the user is who they say they are. Then they pass an ID token in form of a JWT back to the client. Which is used in future requests that Firebase will recognize and know this is who they verified through the server-to-server authentication. In short words, Firebase Authentication is safe and trustworthy, and we can use this securely in our Firestore security rules.

Now let’s use this to only allow authenticated users to read and authenticated users who are also verified can write to our database.

Notice how we also can use functions to simplify writing our rules.

Role-based access

Let’s say we have a user collection. Each user has a role field, defining if they are an administrator, editor, or visitor.

Notice how we can break down read into get(single document) and list(queries and collection). write can be broken into create, update, delete.

All queries done inside the rules will count towards our quota. Also, rules don’t have variables, so we can’t keep the result of getUserData. This is why we pass it down into our other functions.

Custom user claims

There is another way of handling roles, which doesn’t query our user collection. We can use custom user claims. Which simplify our rules and doesn’t eat of our quota.

Custom claims are set by the admin sdk, for example in a Firebase Function like this.

Validate authenticated profile data

Let’s deal with another scenario. We have a message collection and a user collection. Since Firestore is a NoSQL database, we can’t join different collections. And we would like to avoid doubling our queries to get the user who posted the message. Therefore we have a name and profileimg field in the message documents.

Security issue, users can alter the method and change the name and profileimg field and pretend to be someone else. This rule will prevent this.

The Firebase Function way

You have another option when you want to prevent evil users to alter authenticated profile data. You can close all write to the messages collection.

Then use Firestore Functions and retrieve the profile data there. Then use the admin sdk to add the message to the collection, which will bypass the security rules. Firebase Function is a great way to validate and secure data when the security rules become to complex.

Then trigger the function client side (web example).

Doing this, you might not feel the messages are as snappy with the first message. This is because Firebase lowers the functions resources if they are not frequently triggered, and you experience a cold start. This will likely improve in production when they are frequently triggered.


Even though logic is performed client side, the Firestore database can be completely secured. This has only been an introduction to how Firestore security rules work with example rules for some use cases. In the end, your application will decide how your rules end up.

Thank you for reading!

Feel free to follow me on Twitter at @GauteMeekOlsen



Developer at heart

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store