Understanding the Power of Firebase Security Rules — Part 1

Implementing Firebase in your Web, Android or iOS app is quite easy, backed with documentation and examples for each platform.

If you haven’t tried out Firebase and you build for any of these platforms, STOP HERE. GO THERE AND GET STARTED.

After interacting with people using Firebase, beyond setting up User Authentication, I realize that what may not be as easy to do is properly setting up your Firebase rules to protect your database , restrict access to data and validate information being saved.

So I’m doing a three-part series on this — first and second on Firebase Realtime Database Rules and the next on Firebase Storage Rules.

There are three main parts to the Firebase Realtime Database Rules

  • Identifying Your User
  • Controlling Access to Data (Read)
  • Validating Create, Update & Delete Operations

Knowing the user’s identity automatically allows you to set restrictions on what he/she can do (read, update or delete) in the database. Read up on Firebase Authentication.

Firebase provides two options for handling authentication

  • FirebaseUI Auth
    With this and a few lines of code later, you can have a complete sign-in system (code+UI) in your app via Email/Password, Google+, Facebook, GitHub etc. Works on Web, iOS and Android.
  • Firebase SDK Authentication
    Manage your authentication however you choose in addition to using Federated Identity providers like Facebook and Google Sign In.

More on Firebase Authentication.

After a successful sign in, you will have access to the user’s basic profile information and with that you can control the user’s access to/action on data stored.

Database Rules
Firebase is secured using a JSON-formatted Security and Rules language. It is very powerful & flexible. You can access and set your rules from the Database->Rules tab in your Firebase Console.

There are three types of rules:
.read : Describes if and when data is allowed to be read by users.
.write : Describes if and when data is allowed to be written.
.validate : Defines what a correctly formatted value will look like, whether it has child attributes and the data type.

The default rules

Below are different scenarios where these types of rules can come into play

This says: “Anyone can read /foo (and children) but no one can write to it”
This says: “Anyone can read /foo (and children) but only logged in users can write to it”
Grants a user write access on /users/<auth.uid>/ to the user whose unique ID matches the dynamic path, $user_id.
Apply Multiple Firebase Rules
  • Only authenticated users can read data
  • The authenticated user can only write to his own node
  • No one can create a new node apart from within the /users node

One thing you should bear in mind is that the rules you set cascade down the path. Rules shallower in the database override deeper rules.

For example, if you set that /libraries should be readable for only authenticated users, it will not matter if you set that /libraries/lagos should be readable without authentication — it will enforce the authentication requirement first, making it impossible to read /libraries/lagos without an authenticated session.

Using Predefined Variables

Firebase comes with several helpful predefined variables you can use within your security rules to restrict/guide reads, writes and validation. Here they are:

Predefined Variables
auth Represents an authenticated user’s token payload. Already used in the examples above.

now The current time in milliseconds since Linux epoch. Otherwise called “Current Unix Timestamp”.

Ensure that a user’s created time is never set to a time in the future

root A node representing the root path in the Firebase database as it exists before the attempted operation.

Only users who are subscribed can read from the articles node.

newData Contains the data as it would exist after the attempted operation.

Rules stating that any new profile data must have an age, first_name, last_name and state. Otherwise the request will fail

data Contains the data as it existed before the attempted operation.

$ variables A wildcard path used to represent ids and dynamic child keys.

Click here for more about these predefined variables.

Here on, I’ll shorten the rules for display purposes,

"first_name": {".validate": "newData.isString()"}

first_name must be a string

"first_name": {
".validate": "newData.isString() &&
              newData.val().length < 100"
}

first_name must be a string and its length must not exceed 100 characters

"age": {".validate": "newData.isNumber()"}

age must be a number

"age": {".validate": 
"newData.isNumber() && newData.val() >= 18 && newData.val() <= 65"
}

age must be a number between 18 and 65

"angle": {".validate": "newData.isNumber() &&
(newData.val() == 0 ||
newData.val() == 90 ||
newData.val() == 180 ||
newData.val() == 270)"
}

angle must be a number and can only be one of the values specified (0,90,180 or 270).

only messages from the last ten minutes (600000ms) can be read

You can combine these rules as you like them, to handle the different kinds of scenarios you envisage to have.

Thankfully, there’s a SIMULATOR provided on the Firebase console that can help you check and test different scenarios of reads and writes. Go to Database->Rules->Simulator on the Firebase Console. Make sure your rules are well formatted — the Simulator throws errors if it’s not.

While writing your security rules, ensure you end up with a properly formatted JSON file. Thankfully, the editor does a bit of highlighting to help you know if your JSON file is well formatted.

You can also learn more by reviewing the Firebase Security Docs

You should also join the Firebase Slack Channel, ask questions and interact with actual Firebase Engineers, Google Developer Experts and other developers using Firebase.

In Part 2 of this series, I’ll talk some more on Firebase Rules and this time share several example recipes you could copy and modify and in part 3, Storage Rules that can be used to manage how files are uploaded to and accessed in your Firebase Storage. AND IF I can make out the time, build a small app too.

Got questions? Please leave them in the comments section and I’ll be happy to answer them.