Security Quickstart Guide

The Firebase Security API uses a flexible authentication system and an expression-based rules language to provide a very flexible security model. Watch the screencast below to get started:


The Firebase Security API consists of two pieces: Authentication and Security Rules.

Authentication tells Firebase who a user is. Firebase gives you full control over authenticating your users and provides a number of ways of doing so. You can generate auth tokens on your own servers or authenticate using the Firebase Simple Login Client (which provides integrations with several auth providers, and email/password support). Firebase enforces SSL on all connections, so you will never have to send your credentials in the open.

Security Rules tell Firebase what operations should be permitted for a specific user. You upload these rules when you deploy your app, and Firebase enforces them consistently whenever data is accessed. The rules language is extremely flexible and allows you to read data from Firebase, view incoming data, access auth credentials, and more, directly from simple javascript-like expressions.

A Simple Example

Let's walk through an example. We'll be securing a real-time replacement for YouTube comments. You can see the full source on GitHub.

The first thing we need to do is allow users to authenticate. We have several options available to us, but let's do Facebook login using the Firebase Simple Login client. We'll need to include the Firebase Simple Login client (Web, iOS, or Java) and a few lines of code:

var commentsRef = new Firebase("https://FireTube.firebaseIO-demo.com/");

var auth = new FirebaseSimpleLogin(commentsRef, function(error, user) {
  if (!error) {
    // Success!
  }
});

auth.login('facebook');

Firebase* commentsRef = [[Firebase alloc] initWithUrl:@"https://FireTube.firebaseIO-demo.com/"];

FirebaseSimpleLogin* authClient = [[FirebaseSimpleLogin alloc] initWithRef:commentsRef];
[authClient loginToFacebookAppWithId:@"YOUR_APP_ID"
                         permissions:@[@"email"]
                 withCompletionBlock:^(NSError* error, FAUser* user) {
    if (error == nil && user != nil) {
        // Success!
    }
}];

Firebase ref = new Firebase("https://FireTube.firebaseIO-demo.com");
SimpleLogin authClient = new SimpleLogin(ref);

authClient.loginWithEmail("email@example.com", "very secret", new SimpleLoginAuthenticatedHandler() {
  public void authenticated(Error error, User user) {
    if(error != null) {
      // There was an error logging into this account
    }
    else {
      // We are now logged in
    }
  }
});

Adding Some Security Rules

Now that users can log in, we need to define some security rules so that access can be restricted accordingly. Security Rules can be managed from our online editor by going to your Firebase URL in a web browser and clicking the "Security" tab on the left.

First, let's require login. All we need to do is grant write access only if the client has authentication data. Here are our new rules:

{
  "rules": {
    ".read": true,
    ".write": "auth != null"
  }
}

Next, let's make sure that, once posted, comments cannot be modified or deleted. Firebase Rules map to the structure of your data. Since we're storing comments under /comments/commentID, we need to structure our rules the same way so that we can write a rule that applies to each comment individually. We use the "$" to create a variable in our path. The variable takes the place of any child that isn't already listed. It's an easy way to map rules to an entire list of items.

Here are the restructured rules:

{
  "rules": {
    ".read": true,
    "$comment": {
      ".write": "auth != null && !data.exists()"
    }
  }
}

Now we can prevent overwriting or deleting comments simply by checking if data already exists for the specified commentID. We use the "data" variable to access the existing data at this location. This data variable is a RulesDataSnapshot, which behaves very similarly to DataSnapshots in Firebase clients. Here's the modified ".write" rule to make this work:

".write": "auth != null && !data.exists()"

We also want to require that comments have a userid and a string. We can do this using a validation rule. Validation rules are run any time new data is written, and they ensure that your data always conforms to whatever schema you want to enforce. Here we're ensuring there's a userid, a body, and that the body is a string:

{
  "rules": {
    ".read": true,
    "comments": {
      "$comment": {
        ".write": "auth != null",
        ".validate": "newData.hasChildren(['userid', 'body']) && newData.child('body').isString()"
      }
    }
  }
}

Finally, we want to prevent users from spoofing other users. We can do this by modifying the validation rule we just created. We just need to compare the userID being written with the userID in the client's authentication information.

".validate": "auth.id == newData.child('userid').val() && newData.hasChildren(['userid', 'body']) && newData.child('body').isString()"

The Big Picture

The Firebase security model allows you to build secure apps where the client talks directly to the database (Firebase). This eliminates the need to run your own servers or write server code for many apps, thereby removing the application server as a scaling bottleneck. This is especially important for real-time apps, because the persistent network connections that are needed don't work with most server stacks or load balancers.

The Firebase rules language is designed for performance and scale. Its expression-based rules provides fast and predictable execution times and allow Firebase to optimize and cache the results of those expressions.

Another important benefit of the Firebase security model is that it places all of your security logic in one place rather than sprinkling it around your code. Firebase then ensures that your logic is enforced consistently across all parts of your app, regardless of how data is accessed. This makes it very easy to reason about your app's security or do formal security audits. The rules also allow for static analysis, meaning mistakes can be caught immediately when new rules are uploaded.

The Details

When it comes to security, there are a lot of implementation details to take care of. Firebase handles these details for you, so that you can focus on your app and your users. Specifically, Firebase:

  • Requires SSL on all clients
  • Uses strong 2048 bit keys for our SSL certificates
  • Signs authentication tokens with SHA256 HMAC signatures
  • Uses BCrypt for password storage
  • Separates authentication credentials from application data
  • Handles many other mundane (but important) details that keep your data safe.

Next Steps

Now that you've got the basics, you can dive right into our more detailed docs:


Have a suggestion to improve the documentation on this page? Tell us!