Posoroko
Posoroko

Reputation: 281

What security rules should be applied to reads in Firebase?

I created a website for a theatre company with a list of their upcoming shows. Thes dates are stored in firestore, so I put up some rules:

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

I just want the admin to be able to write when they are logged in, but I want everybody to be able to access the database to read the dates.

I thaught it was ok, but I get a new email every day from firebase saying that the database is not secure because anybody can read my data.

What should I do?

Upvotes: 0

Views: 170

Answers (1)

Frank van Puffelen
Frank van Puffelen

Reputation: 599716

Your security rules should allow exactly what your code requires and nothing more. This is known as the principle of least privilege, and is the best way to ensure malicious users can do no more than your own code already does.

Let's look at making reads and writes more secure in turn.

Securing reads

Your rules currently allow anyone to read the entire database. But your code doesn't read the entire database. It instead only reads a list of upcoming shows. So you should only allow reading of upcoming shows:

match /databases/{database}/documents {

  match /upcoming_shows/{document} {
    allow read: if true;
  }

So now users can only read from a single collection: the one named upcoming_shows.


If you actually have a list of all shows, and your code only reads the upcoming shows by using a query, you could also secure that query so that someone reading all shows gets rejected.

As said at the start: your rules should only allow exactly what your code requires, and nothing more.


Securing writes

You said that only the administrator should be allowed to write data when they are logged in. But right now anybody who signs in to Firebase Authentication can write whatever they want in your entire database. So a malicious user can take the configuration from your application, call Firebase with that to sign in, and then for example delete all your data, add their own fake shows to it, or just create an entirely different data set in the database, that you then pay for.

There are two parts that you'll want to better secure:

  1. Only the administrator can write.
  2. They can only add shows.

Only the administrator can write

You know the administrator it seems, so you can probably find their UID in the Firebase console and simply hard-code that in your rules:

allow write: if request.auth == "uid of your known administrator";

Now with these rules, since Firebase determines the UID of the user and it can't be spoofed, you've ensured that only the one person that you identified can write to the database.

There are many variations of this pattern, but this is a good first step.

They can only add shows

With the above changes we already ensured that only the administrator can write, but they can still write whatever they want. The principle of least privilege dictates that we should ensure they can also only write what they must be able to write. In your case that is "adding new shows".

This again breaks down into two requirements:

  1. The administrator can only write shows, meaning they can't write other types of data, or write data elsewhere in the database.

  2. The administrator can only add shows, meaning they can't update or delete them.

Only allow writing of shows

The first requirement is two-fold once more, the first one being similar to what we did for reads: we want to ensure they can only write to the upcoming_shows collection:

match /upcoming_shows/{document} {
    allow write: if request.auth == "uid of your known administrator";
}

The second part is that they can only write shows there, meaning you'll want to validate the data that they write. You'll want to only allow the fields that your code actually writes as (again) the rules should only allow exactly what the code does, and nothing more. This could include validating that the date of the show is in the future, if that is also something that your use-case requires.

Only allow adding shows, not updating/deleting them

Then finally your use-case says they can only add shows, which I read as not updating and/or deleting them. We can use granular rules to implement that requirement:

match /upcoming_shows/{document} {
    allow create: if request.auth == "uid of your known administrator" &&
                  /* the validation rules from the previous step */;
}

Upvotes: 1

Related Questions