Skip to content

Firestore Security Rules Cheat Sheet

Basic Structure

js
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // Match rules go here
  }
}

Match All Documents

js
match /{document=**} {
  allow read, write: if false; // Deny all
}

Basic Read/Write Access

Allow All Reads

js
match /{document=**} {
  allow read: if true;
}

Allow All Writes

js
match /{document=**} {
  allow write: if true;
}

Deny All Access

js
match /{document=**} {
  allow read, write: if false;
}

User Authentication

Allow Only Authenticated Users

js
match /posts/{postId} {
  allow read, write: if request.auth != null;
}

User-Based Document Access

Users Can Only Read/Write Their Own Documents

js
match /users/{userId} {
  allow read, write: if request.auth != null && request.auth.uid == userId;
}

Role-Based Access

Assume a customClaims field is added via Firebase Admin SDK:

js
function isAdmin() {
  return request.auth.token.admin == true;
}

Admin-Only Access

js
match /adminData/{docId} {
  allow read, write: if isAdmin();
}

Field-Level Validation

Only Allow Writes If Specific Fields Meet Conditions

js
match /posts/{postId} {
  allow update: if request.resource.data.keys().hasOnly(['title', 'content']) &&
                request.resource.data.title is string &&
                request.resource.data.content is string;
}

Document Create vs Update

js
match /posts/{postId} {
  allow create: if request.auth != null;
  allow update: if request.auth.uid == resource.data.authorId;
}

Advanced Conditions

Check Document Ownership Before Write

js
match /posts/{postId} {
  allow write: if request.auth.uid == resource.data.authorId;
}

Validate Data on Write

js
match /posts/{postId} {
  allow write: if request.resource.data.title.size() < 100;
}

Collection Group Rules

For subcollections across documents:

js
match /databases/{database}/documents {
  match /users/{userId}/posts/{postId} {
    allow read: if request.auth.uid == userId;
  }
}

Match Nested Collections

js
match /users/{userId} {
  allow read: if request.auth.uid == userId;

  match /posts/{postId} {
    allow read, write: if request.auth.uid == userId;
  }
}

Pagination / Query-Based Rules

You cannot access query parameters in rules. But you can restrict sorting/filtering by only allowing indexes that match the rules.

Always validate all documents in the result:

js
match /posts/{postId} {
  allow read: if resource.data.isPublished == true;
}

Time-Based Access

js
match /events/{eventId} {
  allow read: if resource.data.startTime > request.time;
}

Prevent Changing a Field After Creation

js
match /users/{userId} {
  allow update: if request.resource.data.email == resource.data.email;
}

Allow Users to Create But Not Read

js
match /feedback/{entryId} {
  allow create: if request.auth != null;
  allow read: if false;
}

Allow Public Read, Authenticated Write

js
match /posts/{postId} {
  allow read: if true;
  allow write: if request.auth != null;
}

Enforce Schema / Type Checking

js
match /posts/{postId} {
  allow write: if 
    request.resource.data.title is string &&
    request.resource.data.likes is int &&
    request.resource.data.createdAt is timestamp;
}

Custom Functions

You can create reusable helper functions:

js
function isSignedIn() {
  return request.auth != null;
}

function isOwner(userId) {
  return request.auth.uid == userId;
}

Usage:

js
match /users/{userId} {
  allow read: if isSignedIn() && isOwner(userId);
}

Prevent Deletes

js
match /posts/{postId} {
  allow delete: if false;
}

Allow Access to Own Posts Only

js
match /posts/{postId} {
  allow read, write: if request.auth.uid == resource.data.userId;
}

Allow Writes for a Limited Time Period

js
match /submissions/{id} {
  allow write: if request.time < timestamp.date(2025, 3, 30);
}

Read-Only Admin Panel

js
match /admin/{docId} {
  allow read: if isAdmin();
  allow write: if false;
}

Tips & Gotchas

  • Rules are NOT filters — they do not limit query results after retrieval. Every document must individually match the rule.
  • Always test rules in the Firebase console or via the emulator.
  • Always validate the schema manually in the rules if needed.
  • Avoid overly complex rules — split access into documents or subcollections when needed.