Security Rules

Security Rules in Oracle Backend with Firebase APIs 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.

Note: When a JavaScript application is offline, supported writes can appear in its local view before the backend evaluates Security Rules. If the backend rejects a queued write, the SDK rolls back its local effect.

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

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

Fixed Variables

Oracle Backend with Firebase APIs 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:

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.

Operators and Functions

Security rules support 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 with Firebase APIs 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;

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;
}

Macros and Functions

Oracle Backend with Firebase APIs 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";

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;
}

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;
}

Best Practices