Firestore Security Rules: Complete Access Control Guide
In this tutorial, you will learn about Firestore Security Rules: Complete Access Control Guide. We cover key concepts, practical examples, and best practices to help you master this topic.
Firestore Security Rules control read and write access to your database by evaluating each request against conditions like user authentication, document data, and request path patterns.
What You'll Learn
How to write Firestore Security Rules that restrict access to authorized users, validate data structure, implement role-based permissions, and test rules before deploying.
Why It Matters
Misconfigured security rules are the most common Firebase vulnerability. DodaTech's Durga Antivirus Pro uses rules to ensure users can only read their own devices and scan data — preventing data leaks across tenants.
Real-World Use
A multi-tenant security app: each user sees only their own devices. Admins can read all data. Write operations validate threat levels and prevent malicious data injection.
flowchart LR
A["Request\nRead device/doc"] --> B["Security Rules\nEvaluate"]
B --> C{"request.auth\n!= null?"}
C -->|No| D["DENY"]
C -->|Yes| E{"resource.data.userId\n== request.auth.uid?"}
E -->|No| D
E -->|Yes| F["ALLOW"]
style D fill:#fecaca,stroke:#dc2626
style F fill:#bbf7d0,stroke:#16a34a
Basic Auth Check
// Allow access only to authenticated users
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// All authenticated users can read
match /{document=**} {
allow read: if request.auth != null;
}
// Only authenticated users can write
match /{document=**} {
allow write: if request.auth != null;
}
}
}
User-Owned Data Pattern
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// Each user can only read/write their own documents
match /users/{userId} {
allow read, write: if request.auth != null
&& request.auth.uid == userId;
}
// Devices belong to a user
match /users/{userId}/devices/{deviceId} {
allow read: if request.auth != null
&& request.auth.uid == userId;
allow write: if request.auth != null
&& request.auth.uid == userId
&& request.resource.data.userId == userId;
}
}
}
Role-Based Access Control
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// Helper function to check user role
function isAdmin() {
return request.auth != null
&& get(/databases/$(database)/documents/admins/$(request.auth.uid))
.data.role == 'admin';
}
// Admins can read all documents
match /{document=**} {
allow read: if isAdmin();
}
// Regular user access
match /users/{userId}/devices/{deviceId} {
allow read: if request.auth != null
&& (request.auth.uid == userId || isAdmin());
allow write: if request.auth.uid == userId;
}
// Admin-only functions
match /scans/{scanId} {
allow read: if isAdmin();
allow write: if false; // Written by Cloud Functions only
}
}
}
Data Validation
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /devices/{deviceId} {
allow create: if request.auth != null
// Validate required fields
&& request.resource.data.keys().hasAll(['name', 'os', 'userId'])
// Validate field types
&& request.resource.data.name is string
&& request.resource.data.os is string
// Validate field values
&& request.resource.data.os in ['Windows', 'macOS', 'Linux', 'Android', 'iOS']
// Prevent setting protected fields
&& request.resource.data.role == null;
allow update: if request.auth != null
// Prevent changing owner
&& request.resource.data.userId == resource.data.userId;
}
}
}
Testing Rules in Console
// Use the Rules Playground in Firebase Console to test:
// - Simulate auth state (authenticated / unauthenticated)
// - Pick a document path
// - Choose read/write operation
// - View whether the rule allows or denies
// Example test scenario:
// Path: /users/user_abc123/devices/dev_001
// Auth: Authenticated with uid = "user_abc123"
// Operation: Read
// Expected: ALLOW
// Path: /users/user_abc123/devices/dev_001
// Auth: Authenticated with uid = "user_def456"
// Operation: Read
// Expected: DENY
Common Mistakes
1. Leaving Rules Open During Development
Default rules during development often allow read, write: if true. This is dangerous even in test mode. Use test credentials and restrict access from the start.
2. Not Using Granular Rules
Broad rules like match /{document=**} { allow read: if true; } expose your entire database. Scope rules to specific collections and paths.
3. Confirming Ownership with Only the Document ID
A user claiming userId = "admin" in the document data can fake ownership. Always use request.auth.uid — the server-verified auth token — not document data.
4. Ignoring the resource vs request.resource Distinction
resource is the existing document data. request.resource is the new data being written. Use request.resource to validate incoming writes, resource to check current state.
5. Not Handling Deletes
A delete operation triggers write rules. If you allow write but intend to prevent deletes, use allow delete: if false; explicitly.
Practice Questions
- What is the difference between
resourceandrequest.resourcein rules? - How do you check if a user is authenticated in Security Rules?
- What happens when a rule evaluates to
false? - How do you implement role-based access in Firestore rules?
Answers:
resourceis the current document data on the server.request.resourceis the incoming data for writes. Userequest.resourcefor create/update validation.- Check
request.auth != null. Therequest.auth.uidcontains the user's unique ID from Firebase Auth. - The request is denied. Firestore returns a permission-denied error to the client.
- Store roles in a
usersoradminscollection. Useget()within rules to fetch the role and compare with required permissions.
Challenge: Write security rules for Durga Antivirus Pro that allow users full access to their own devices and scans, allow admins read access to everything, validate that scan reports don't exceed field limits, and prevent users from deleting scan records.
FAQ
Mini Project
Write and test a complete Security Rules set: user-owned devices collection, admin read access, data validation on create, field protection on update, and delete prevention for scan records. Test each scenario in the Rules Playground.
What's Next
Firestore Indexes — optimize query performance with Composite and collection group indexes.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro