Set Up Cloud Firestore Security Rules

First Published: 14 September 2018
Updated on: 24 September 2018

With the Cloud Firestore Security Rules, we can focus on building a great user experience, without having to manage infrastructure or write server-side authentication and authorization code.

The idea is to authenticate users through Firebase Authentication and set up rules to determine who has access to data stored in Cloud Firestore.

You can find your security rules in the Rules tab in the Cloud Firestore section of the Firebase Console.

Firestore Security Rules

Securing Firestore

To start securing our database we need to understand how the security rules work, let’s take a look at the default ones that come when you create the app.

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

The security rules work matching documents in the database, they have two permissions, read and write which are both false by default, meaning, no one has access to the database.

To start working with them, we tell them to allow all read/write operations, since we’re going to be in development mode:

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write;
    }
  }
}

The =\*\* symbol is a cascade operator. Rules don’t cascade by default.

So if you set up a read/write rule for the document users/{userId} but don’t set up read/write rules for users/{userId}/tasks/{taskId} no one will have access to the taskId documents.

When you use the =\*\* operator, you’re telling Firestore rules that if the user matches the condition to read that document, they should be able to read all the sub-collections and documents below that tree.

The brackets mean we’re using a wild-card, for example, if I have a collection called users that has the documents for each user’s profile, I’d only want the profile owner to be able to have read/write access.

service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{userId} {
      allow read, write: if request.auth.uid == userId;
    }
  }
}

Notice how we’re getting the user’s uid from the request object. When working with Firestore rules, we have two available objects.

The request object has information about the request made, such as the authenticated user: request.auth, and the time the request was made: request.time.

The resource object is THE Firestore document we’re accessing. For example, let’s say we have public and private profiles, each profile has a flag called public and it’s either set to true or false.

The resource object gives us access to that flag:

service cloud.firestore {
  match /databases/{database}/documents {

    match /myCollection/myDocument {
      allow read: if resource.data.public == true;
    }
  }
}

In that case, people will only be able to read profiles marked as public.

We can only compare with fields in other documents in the Firestore database (we’ll do that when we’re securing our app).

If you want to take a deeper dive on Ionic + Firestore you should go through my FREE course: Build your first Firestore powered Ionic app.