21 Security Rules

Security Rules in Oracle Backend for Firebase define access control for database documents, collections, and storage objects. They determine who can access what data, under what conditions, and which operations are permitted. Rules are written in a declarative format using CEL (Common Expression Language) and are evaluated at runtime for every read or write request. These rules are essential for protecting sensitive data and enforcing business logic.

This chapter explains the structure, syntax, variables, and best practices for writing security rules for documents, collections, joins, and storage.

21.1 Rule Structure

Each rule is defined using the following structure:

match <path> {
  allow <methods>: if <condition>;
}
Component Description

match

Specifies the document or collection path the rule applies to.

allow

Defines the permitted operations: get, list, create, update, delete.

if

A conditional expression that must evaluate to true for access to be granted.

Supported Methods

Component Description

get

Read a single document

list

Query multiple documents

read

Applies to both single document reads and collection reads. Used only when get or list is not explicitly defined.

create

Add a new document

update

Modify an existing document

write

Applies to all write operations (create, update, delete). Used only when no specific write methods are defined.

delete

Remove a document

21.2 Fixed Variables

Oracle Backend for Firebase provides the following built-in variables to use in rule conditions:

request

request represents the incoming request from the client and has the following properties:

  • request.auth: Authentication context (such as, user ID-uid, email, displayName)

  • request.resource.data: Data being written or updated

  • request.time: ISO 8601 UTC Timestamp of the request

  • request.method: Operation type ( such as get, list, create)

  • request.path: Full path of the document or collection (For example,
    /user/user123/recipes
    )
  • request.path_arr: Path as array (For example, ["user","user123","recipes"])

resource

resource represents the existing document in the database and has the following property:

resource.data: Current document data, which is used for read operations and conditional updates

auth

auth is the shortcut for request.auth.

time

time is the shortcut for request.time.

21.3 Operators and Functions

Security rules support a the following set of operators and CEL functions:

Table 21-1 Operators

Operator Description

==, !=

Equality and inequality

>, <, >=, <=

Comparison

&&, `

Logical operations

-, /, %, *

Math operations

in, is

Membership and type checks

a[i], a.f

Index and field access

CEL Functions

Oracle Backend for Firebase supports CEL functions for strings, lists, math, and timestamps.

Table 21-2 String Functions

Operator Example

lower()

'Burger'.lower() == 'burger'

upper()

'Burger'.upper() == 'BURGER'

matches()

'Chocolate Chip'.matches('.*Chip') == true

replace()

'ChocolateChip'.replace("Chip","Coco") == 'ChocolateCoco'

size()

'ChocolateChip'.size() == 13

split()

'A,B,C'.split(',') == ['A','B','C']

trim()

' A B '.trim() == 'AB'

Table 21-3 List Functions

Operator Example

concat()

['A'].concat(['B']) == ['A','B']

hasAll()

['A','B'].hasAll(['A']) == true

hasAny()

['A','B'].hasAny(['C','B']) == true

hasOnly()

['A','B'].hasOnly(['A','B','C']) == true

size()

['A','B'].size() == 2

Table 21-4 Math Functions

Operator Example

abs()

abs(-5) == 5

ceil()

ceil(4.2) == 5

floor()

floor(4.8) == 4

pow()

pow(2,3) == 8

round()

round(4.6) == 5

sqrt()

sqrt(9) == 3

Table 21-5 Timestamp Functions

Operator Example

year()

request.time.year() == 2025

month()

request.time.month() == 11

day()

request.time.day() == 8

dayOfWeek()

request.time.dayOfWeek() == 1..7

dayOfYear()

request.time.dayOfYear()

hours()

request.time.hours() == 14

minutes()

request.time.minutes() == 30

seconds()

request.time.seconds() == 15

nanos()

request.time.nanos() == 0

toMillis()

request.time.toMillis()

Example 21-1

allow update: if request.auth != null &&
               request.auth.uid == resource.data.ownerId &&
               request.time.year() == 2025;

21.4 Wildcard Rules

Wildcards allow rules to apply to multiple documents or collections using variable placeholders. Wildcards can be used in both path matching and condition logic.

match /users/{userId}/recipes/{recipeId} {
  allow update: if request.auth.uid == userId;
}

21.5 Macros and Functions

Oracle Backend for Firebase supports macros like exists() and get() to reference other documents in rules.

allow create: if exists(/users/$(request.resource.data.ownerId));

Using exists()

exists(path) returns true if the document at the given path exists.

allow create: if exists(/users/$(request.resource.data.ownerId));

get()

get(path) returns the document object at the given path.

allow get: if get(/projects/$(projectId)).data.status == "active";

21.6 Rule Examples

Example 21-2 Owner-Based Update

match /users/{userId}/recipes/{recipeId} {
  allow update: if request.auth.uid == resource.data.uuid;
}

Example 21-3 Public Read with Fallback to Owner

match /posts/{postId} {
  allow get: if resource.data.isPublic == true ||
             request.auth.uid == resource.data.ownerId;
}

Example 21-4 Restrict Creation Based on Field

match /posts/{postId} {
  allow create: if request.resource.data.isPublic == true;
}

Example 21-5 List Only Public Documents

match /posts/{postId} {
  allow list: if request.auth != null &&
              resource.data.isPublic == true;
}

21.7 Collection Group and Join Collection Rules

Collection Group Rules

Collection Group queries require rules that match the subcollection path and define access conditions.

match /users/{userId}/recipes/{recipeId}/notes/{noteId} {
  allow list: if request.auth != null;
}

Join Collection Rules

Join queries must be backed by rules that match the join path and validate access.

match /EMP_DEP/_docId {
  allow get: if request.auth != null;
}

21.8 Best Practices

  • Always define rules before deploying queries.

  • Use wildcards to generalize access control.

  • Validate both request and resource for write operations.

  • Use macros like exists() to enforce relational integrity.

  • Keep rules readable and modular.