Firestore Security Rules Standards
Intermediate
Enforce secure Firestore Security Rules patterns — deny by default, field validation, ownership checks, custom functions, and mandatory testing requirements.
File Patterns
**/firestore.rules**/firebase.json**/firestore.indexes.json
This rule applies to files matching the patterns above.
Rule Content
rule-content.md
# Firestore Security Rules Standards
## Rule
All Firestore collections MUST have explicit security rules. Default deny everything, then allow specific operations with proper authentication, validation, and ownership checks.
## Format
```
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// Helper functions at top
function isAuthenticated() {
return request.auth != null;
}
function isOwner(userId) {
return request.auth.uid == userId;
}
// Collection-specific rules
match /collection/{docId} {
allow read: if <condition>;
allow create: if <condition> && <validation>;
allow update: if <condition> && <validation>;
allow delete: if <condition>;
}
}
}
```
## Requirements
### Authentication
- ALL write operations MUST require authentication
- Public reads only for explicitly public collections
- Admin operations require custom claims verification
### Field Validation
```
allow create: if isAuthenticated()
&& request.resource.data.keys().hasAll(['title', 'content', 'authorId'])
&& request.resource.data.title is string
&& request.resource.data.title.size() > 0
&& request.resource.data.title.size() <= 200
&& request.resource.data.authorId == request.auth.uid;
```
### Ownership Verification
```
allow update: if isOwner(resource.data.authorId)
&& request.resource.data.authorId == resource.data.authorId; // Cannot change author
```
## Examples
### Good
```
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
function isAuthenticated() {
return request.auth != null;
}
function isAdmin() {
return request.auth.token.admin == true;
}
match /posts/{postId} {
allow read: if resource.data.published == true || isOwner(resource.data.authorId);
allow create: if isAuthenticated()
&& request.resource.data.keys().hasAll(['title', 'content', 'authorId', 'published'])
&& request.resource.data.authorId == request.auth.uid
&& request.resource.data.title is string
&& request.resource.data.title.size() <= 200;
allow update: if isOwner(resource.data.authorId) || isAdmin();
allow delete: if isOwner(resource.data.authorId) || isAdmin();
}
}
}
```
### Bad
```
// NEVER DO THIS IN PRODUCTION
match /{document=**} {
allow read, write: if true;
}
// No validation
match /posts/{postId} {
allow write: if request.auth != null; // No field validation!
}
```
## Enforcement
Test ALL rules with Firebase Emulator and @firebase/rules-unit-testing.
Run rule tests in CI before deploying.
Review security rules in every PR that modifies firestore.rules.FAQ
Discussion
Loading comments...