Firestore Security Rules Data Validation with Type Checking (typeof)

So you want to do something like typeof var (JavaScript) In Firebase Firestore security rules? There will be times when you will want to check the type of a certain piece of data to do things like:

  • Incoming data (input) validation.
  • Check the type of an existing resource’s (document) data field in if condition expressions.

Security Rules language is not JavaScript itself. It is just an expression language that borrows its look and feel from JS. So we cannot do something like typeof var or var instanceof TYPE.

Instead, we can use the is operator (similar to instanceof in JS). Let’s see the different data types that we can check for, using is:

value is bool
value is int
value is float
value is number (works for both int and float)
value is string
value is list
value is map
value is timestamp
value is duration
value is path
value is latlng

So based on this, lets now look at a couple of examples that allow/deny access based on type checking:

// Allow create and update of document if the name being
// passed is of a string type
allow write: if request.resource.data.name is string;

// Allow get and list if the underlying document being accessed
// has an accessPermissions map/hash/dict with a public field
// which is set to true
allow read: if resource.data.accessPermissions is map
               && resource.data.accessPermissions.public is bool
               && resource.data.accessPermissions.public == true;

// We can also type check variables inside a function
function isUserAdmin(userId) {
  let user = get(/databases/$(database)/documents/users/$(userId)).data;
  let isUserAdmin = user.role is string && user.role == 'admin';

  return isUserAdmin;
}
allow read, write: isUserAdmin(req.auth.uid);

Based on the examples above, it is now easier to understand why type checking is important. If we skip type checking and a condition expression leads to an error due to that, the overall rule will evaluate to false on runtime which will effectively deny access.

A condition that evaluates to false or causes an error denies access. Only a condition that evaluates to true allows access.

So if we tried to access resource.data.mapField.key where mapField is not really a map itself, it’ll cause a runtime error which will deny access.

Leave a Reply

Your email address will not be published.