Skip to content

Firestore Security Rules — Complete Guide

DodaTech Updated 2026-06-24 2 min read

In this tutorial, you'll learn about Firestore Security Rules. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.

The Problem

Your Firestore data is read/writable by anyone (insecure rules), or your authenticated users can't access their own data.

Wrong Approach ❌

// Insecure: anyone can read/write everything
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if true; // DANGER: open to the world!
    }
  }
}

Output: Anyone with your project ID can read/write all data.

Right Approach ✅

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {

    // User profiles — only owner can access
    match /users/{userId} {
      allow read: if request.auth != null && request.auth.uid == userId;
      allow write: if request.auth != null && request.auth.uid == userId
                    && request.resource.data.name is string
                    && request.resource.data.name.size() < 100;
    }

    // Public data — anyone can read, only admins can write
    match /public/{document} {
      allow read: if true;
      allow write: if request.auth != null
                    && get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == 'admin';
    }

    // Posts — authenticated users can create, owners can update
    match /posts/{postId} {
      allow create: if request.auth != null
                     && request.resource.data.authorId == request.auth.uid
                     && request.resource.data.title is string
                     && request.resource.data.title.size() > 0;
      allow read: if true;
      allow update: if request.auth != null
                     && resource.data.authorId == request.auth.uid;
      allow delete: if request.auth != null
                     && resource.data.authorId == request.auth.uid;
    }

    // Data validation example
    match /reviews/{reviewId} {
      allow write: if request.auth != null
                    && request.resource.data.rating is number
                    && request.resource.data.rating >= 1
                    && request.resource.data.rating <= 5
                    && request.resource.data.text is string
                    && request.resource.data.text.size() <= 1000;
    }
  }
}

Output: Properly secured Firestore with user-specific access.

Prevention

  • Start with deny all and grant specific access.
  • Use request.auth.uid for user-specific rules.
  • Validate data types and sizes with request.resource.data.
  • Use get() and exists() for cross-document validation.
  • Test rules in Firebase Console > Firestore > Rules playground.

Common Mistakes with firestore security rule

  1. Using head and tail instead of pattern matching, causing runtime errors on empty lists
  2. Forgetting that lazy evaluation defers computation until the value is forced, causing space leaks with unevaluated thunks
  3. Using return to exit a function early instead of wrapping a pure value in the monad

These mistakes appear frequently in real-world ANDROID code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.

Practice Exercise

Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.

This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.

FAQ

### What is the difference between resource and request.resource?

resource is the existing document data (before the write). request.resource is the new data being written. For read operations, resource contains the document data.

### Can I test security rules locally?

Use the Firebase Emulator Suite. Run <a href="/apis/firebase/">Firebase</a> emulators:start and test rules with the Rules Unit Testing Library (JavaScript).

### How do I allow admin access?

Check a user role in the rules: get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == 'admin'. Set this role in Firestore admin documents.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro