Firestore Security Rules Functions — Advanced Access Control with Custom Functions
In this tutorial, you will learn about Firestore Security Rules Functions. We cover key concepts, practical examples, and best practices to help you master this topic.
Firestore security rules functions allow you to define reusable validation logic, encapsulating authentication checks, role verification, data validation, and cross-document authorization in modular functions.
What You'll Learn
- Writing and using helper functions in security rules
- Creating role-based access control functions
- Validating document data with custom functions
Why It Matters
Functions reduce security rules duplication and complexity. Without functions, rules become long, error-prone, and hard to maintain. DodaTech uses security rules functions for consistent authorization across its Firestore collections.
flowchart TD
A["Security Rules"] --> B["Helper Functions"]
B --> C["isAuthenticated()"]
B --> D["isAdmin()"]
B --> E["isOwner(userId)"]
B --> F["isInProject(projectId)"]
C --> G["Reused across all collections"]
D --> G
E --> G
F --> G
Code Examples
// Firestore security rules with functions
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// ===== Helper Functions =====
// Authentication check
function isAuthenticated() {
return request.auth != null;
}
// Role checks
function isAdmin() {
return isAuthenticated()
&& request.auth.token.admin == true;
}
function hasRole(role) {
return isAuthenticated()
&& request.auth.token.roles.hasAny([role]);
}
// Ownership check
function isOwner(userId) {
return isAuthenticated()
&& request.auth.uid == userId;
}
// Data validation
function isValidEmail(email) {
return email.matches('^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$');
}
function isValidTimestamp(timestamp) {
return timestamp >= timestamp.value(0)
&& timestamp <= request.time;
}
// Cross-document checks
function belongsToProject(projectId) {
return isAuthenticated()
&& get(/databases/$(database)/documents/projects/$(projectId))
.data.members.hasAny([request.auth.uid]);
}
// ===== Rules =====
match /users/{userId} {
allow read: if isAuthenticated();
allow create: if isOwner(userId)
&& request.resource.data.name is string
&& isValidEmail(request.resource.data.email);
allow update: if isOwner(userId) || isAdmin();
allow delete: if isAdmin();
}
match /projects/{projectId} {
allow read: if belongsToProject(projectId);
allow write: if hasRole('project_manager')
&& belongsToProject(projectId);
}
match /tasks/{taskId} {
allow read: if belongsToProject(
resource.data.projectId);
allow create: if belongsToProject(
request.resource.data.projectId);
allow update: if isOwner(resource.data.assignedTo)
|| hasRole('project_manager');
}
}
}
// Advanced: Rate limiting and conditional checks
function isWithinLimit(collectionName, maxCount) {
return isAuthenticated()
&& get(
/databases/$(database)/documents/$(collectionName)/$(request.auth.uid)
).data.count < maxCount;
}
function isBusinessHours() {
return request.time >= timestamp.value(
Date.parse('2026-01-01T09:00:00Z'))
&& request.time <= timestamp.value(
Date.parse('2026-01-01T17:00:00Z'));
}
match /apiRequests/{requestId} {
allow create: if isAuthenticated()
&& isWithinLimit('userQuotas', 100)
&& isBusinessHours();
}
# Test security rules with Firebase Emulator
firebase emulators:start
# Run rules tests
firebase emulators:exec 'npm run test:rules'
Common Mistakes
1. Making Functions Too Complex
Rules functions have execution time limits. Keep functions simple and fast.
2. Not Testing Rules Functions Thoroughly
Functions introduce logic that must be tested with the emulator for each scenario.
3. Using Functions for Side Effects
Security rules functions cannot have side effects. They only evaluate conditions.
4. Forgetting That Functions Run in a Restricted Environment
Not all JavaScript features are available. Use only Firestore rules expression syntax.
5. Hardcoding Values Inside Functions
Use parameters and configuration documents instead of hardcoded values.
Practice Questions
- How do you define a function in Firestore security rules?
- Can rules functions call other functions?
- What built-in objects are available in rules functions?
- How do you access document fields in a function?
- Can rules functions make HTTP requests?
Answers:
- Using the function keyword: function name() { ... }
- Yes. Functions can call other functions defined in the rules file.
- request, resource, auth, firestore (get, exists, getAfter, existsAfter).
- Use resource.data.fieldName or request.resource.data.fieldName.
- No. Security rules cannot make HTTP requests or external API calls.
Challenge: Write a complete security rules system for a task management app with users, projects, tasks, and comments. Use functions for role checks, project membership, data validation, and audit logging. Test every rule scenario with the Firebase Emulator.
FAQ
Mini Project
Build a comprehensive Firestore security rules system for a multi-tenant SaaS application. Create functions for tenant isolation, role-based access, data validation, and Rate Limiting. Include automated tests that verify each function's behavior using the Firebase Emulator.
What's Next
Learn about security rules validation for data integrity checks, then explore offline data persistence for Firestore.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro