You're viewing the legacy docs. They are deprecated as of May 18, 2016.
Go to current docs

Security & Rules Guide

User Based Security

This document revisits concepts from Securing Your Data, incorporating the predefined auth variable to create a complete solution for securing our data.

Overview

This guide explains how to combine the Security and Firebase Rules language with authentication information about your users. By combining these two concepts, you can control access to data based on user identity.

Authenticated users assumed

Implementation of authenticating users varies depending on your platform. Please refer to the authentication guide for your platform: Web, iOS, Android, REST.

The auth Variable

The predefined auth variable is null before authentication takes place. Once a user is authenticated by Firebase Login's auth method, it will contain the following attributes:

provider The authentication method used ("password", "anonymous", "facebook", "github", "google", or "twitter").
uid A unique user id, guaranteed to be unique across all providers.

Have a look at some valid rules utilizing the auth variable:

{
  "rules": {
    "users": {
      "$user_id": {
        // grants write access to the owner of this user account
        // whose uid must exactly match the key ($user_id)
        ".write": "$user_id === auth.uid"
      }
    }
  }
}

Using Custom Tokens

Internally, Firebase utilizes one of our Token Generator Libraries. It is also possible to go right to the source and create custom tokens yourself, here's two example using Node.js and Java:

var FirebaseTokenGenerator = require("firebase-token-generator.js");
var tokenGenerator = new FirebaseTokenGenerator(FIREBASE_SECRET);
var token = tokenGenerator.createToken({ "uid": "1", "hasEmergencyTowel": true });
// Generate a new secure JWT
Map<String, Object> payload = new HashMap<String, Object>();
payload.put("uid", "1");
payload.put("hasEmergencyTowel", true);

TokenGenerator tokenGenerator = new TokenGenerator(YOUR_FIREBASE_SECRET);
String token = tokenGenerator.createToken(payload);

System.out.println(token);

Any values passed into createToken() are appended onto the auth variable for use in your Security and Firebase Rules. With the token created above, we could write rules like the following:

{
  "rules": {
    "frood": {
      // A towel is about the most massively useful thing an interstellar
      // hitchhiker can have
      ".read": "auth.hasEmergencyTowel === true"
    }
  }
}

Read more about custom authentication tokens in our User Authorization Guide.

Revisiting the Chat Example

Let's build on the chat example from Securing Your Data and add in some user authentication, pulling all these concepts together into a working app:

{
  "rules": {
    "room_names": {
      // any logged in user can get a list of room names
      ".read": "auth !== null",

      "$room_id": {
        // this is just for documenting the structure of rooms, since
        // they are read-only and no write rule allows this to be set
        ".validate": "newData.isString()"
      }
    },

    "members": {
       // I can join or leave any room (otherwise it would be a boring demo)
       // I can have a different name in each room just for fun
       "$room_id": {
          // any member can read the list of member names
          ".read": "data.child(auth.uid).exists()",

          // room must already exist to add a member
          ".validate": "root.child('room_names/'+$room_id).exists()",

          "$user_id": {
             ".write": "auth.uid === $user_id",
             ".validate": "newData.isString() && newData.val().length > 0 && newData.val().length < 20"
          }
       }
    },

    "messages": {
      "$room_id": {
        // the list of messages for a room can be read by any member
        ".read": "root.child('members/'+$room_id+'/'+auth.uid).exists()",

        // room we want to write a message to must be valid
        ".validate": "root.child('room_names/'+$room_id).exists()",

        "$message_id": {
          // a new message can be created if it does not exist, but it
          // cannot be modified or deleted
          // any member of a room can write a new message
          ".write": "root.child('members/'+$room_id+'/'+auth.uid).exists() && !data.exists() && newData.exists()",

          // the room attribute must be a valid key in room_names/ (the room must exist)
          // the object to write must have a name, message, and timestamp
          ".validate": "newData.hasChildren(['user', 'message', 'timestamp'])",

          // the message must be written by logged in user
          "user": {
             ".validate": "newData.val() === auth.uid"
          },

          // the message must be longer than 0 chars and less than 50
          "message": { ".validate": "newData.isString() && newData.val().length > 0 && newData.val().length < 50" },

          // messages cannot be added in the past or the future
          // clients should use Firebase.ServerValue.TIMESTAMP to ensure
          // accurate timestamps
          "timestamp": { ".validate": "newData.val() <= now" },

          // no other fields can be included in a message
          "$other": { ".validate": false }
        }
      }
    }
  }
}
Try it on JSFiddle

Feel free to test it out! This interactive demo, written in JavaScript, authenticates to GitHub's OAuth API using Firebase Authentication, and enforces all of the Security and Firebase Rules above in a functional chat demo.