Firebase Security Guide: Firestore Rules and Authentication

Share

TL;DR

Firebase security depends on Firestore Security Rules (or Realtime Database Rules). Without proper rules, anyone can read and write your data. The Firebase config object is safe to expose, but your security rules are what actually protect your data. Write rules that verify user identity with request.auth, validate data structure, and test thoroughly before deploying.

Firebase Security Model

Firebase lets your frontend talk directly to the database. Security is enforced through rules that run on Firebase's servers, not your code. Understanding this is essential:

  • Config is public: Your Firebase config (apiKey, etc.) can be in your frontend code
  • Rules are your security: Security rules determine what users can access
  • Client-side code is untrusted: Never rely on frontend code for security
  • Authentication provides identity: Rules use auth state to make decisions

Key concept: The Firebase API key is not a secret. It's like a project identifier. Your Firestore Security Rules are what actually protect your data.

Firestore Security Rules Basics

The Danger of Test Mode

When you create a Firebase project, you might start in "test mode" which allows all access:

DANGEROUS: Test mode rules (allow all)
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      // This allows ANYONE to read and write EVERYTHING
      allow read, write: if true;
    }
  }
}

Never deploy with test mode rules. This is equivalent to having no security at all. Anyone who finds your Firebase project can read, modify, or delete all your data.

Basic Secure Rules

Secure starting point
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // Deny all by default
    match /{document=**} {
      allow read, write: if false;
    }

    // Users can only access their own document
    match /users/{userId} {
      allow read, write: if request.auth != null
                         && request.auth.uid == userId;
    }

    // Public posts are readable, authors can write
    match /posts/{postId} {
      allow read: if resource.data.published == true;
      allow create: if request.auth != null;
      allow update, delete: if request.auth != null
                            && request.auth.uid == resource.data.authorId;
    }
  }
}

Common Security Rules Patterns

Pattern 1: User-Owned Data

Users can only access their own documents
match /profiles/{userId} {
  allow read, write: if request.auth != null
                     && request.auth.uid == userId;
}

// For subcollections owned by users
match /users/{userId}/notes/{noteId} {
  allow read, write: if request.auth != null
                     && request.auth.uid == userId;
}

Pattern 2: Data Validation

Validate data on write
match /posts/{postId} {
  allow create: if request.auth != null
    // Validate required fields exist
    && request.resource.data.keys().hasAll(['title', 'content', 'authorId'])
    // Validate title length
    && request.resource.data.title.size() <= 200
    // Validate authorId matches the user
    && request.resource.data.authorId == request.auth.uid
    // Validate content is a string
    && request.resource.data.content is string;
}

Pattern 3: Role-Based Access

Check user roles from a separate document
// Helper function to check admin status
function isAdmin() {
  return get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == 'admin';
}

match /adminData/{docId} {
  allow read, write: if request.auth != null && isAdmin();
}

match /users/{userId} {
  // Users can read their own data
  allow read: if request.auth != null && request.auth.uid == userId;
  // Only admins can write to any user
  allow write: if request.auth != null && isAdmin();
}

Pattern 4: Time-Based Rules

Prevent rapid writes (rate limiting)
match /comments/{commentId} {
  allow create: if request.auth != null
    // Check if user has commented recently (basic rate limit)
    && (!exists(/databases/$(database)/documents/userMeta/$(request.auth.uid))
        || get(/databases/$(database)/documents/userMeta/$(request.auth.uid)).data.lastComment
           < request.time - duration.value(30, 's'));
}

Firebase Authentication Security

Secure Sign-Up Configuration

Configure authentication properly in Firebase Console:

Authentication Security Checklist

Enable only the auth providers you actually use

Set password requirements (length, complexity)

Enable email verification for email/password auth

Configure authorized domains (don't allow all)

Set up proper OAuth redirect URLs

Review and limit sign-up rate if needed

Custom Claims for Authorization

Set custom claims (server-side)
// In Cloud Functions or Admin SDK
const admin = require('firebase-admin');

// Set admin claim for a user
await admin.auth().setCustomUserClaims(userId, { admin: true });

// The claim will be available in security rules:
// request.auth.token.admin == true
Use custom claims in rules
match /adminOnly/{docId} {
  allow read, write: if request.auth != null
                     && request.auth.token.admin == true;
}

Cloud Storage Security Rules

Firebase Storage also needs security rules:

Storage security rules
rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {
    // User profile images
    match /users/{userId}/profile.jpg {
      allow read: if true;  // Public profile images
      allow write: if request.auth != null
                   && request.auth.uid == userId
                   && request.resource.size < 5 * 1024 * 1024  // 5MB max
                   && request.resource.contentType.matches('image/.*');
    }

    // Private user files
    match /users/{userId}/private/{fileName} {
      allow read, write: if request.auth != null
                         && request.auth.uid == userId;
    }

    // Deny everything else
    match /{allPaths=**} {
      allow read, write: if false;
    }
  }
}

Testing Security Rules

Firebase provides tools to test your rules before deploying:

Firebase Emulator

Run security rules tests
// Install Firebase CLI
npm install -g firebase-tools

// Start emulators
firebase emulators:start

// Run tests
firebase emulators:exec --only firestore "npm test"

Rules Playground

In Firebase Console, use the Rules Playground to simulate requests:

  1. Go to Firestore > Rules > Edit rules
  2. Click "Rules Playground"
  3. Simulate different auth states and operations
  4. Verify rules allow/deny as expected

Common Firebase Security Mistakes

MistakeRiskFix
Test mode in productionAnyone can read/write all dataWrite proper security rules
Trusting client dataUsers can send any dataValidate all fields in rules
Not checking authUnauthenticated accessAlways check request.auth
Overly broad rulesAccess to unintended dataUse specific path matches
Storing secrets in FirestoreExposure via rules bypassUse Cloud Functions for secrets

Is my Firebase API key secure?

The Firebase API key (and other config values) are designed to be public. They identify your project but don't grant access. Your security comes from Firestore Security Rules, not from hiding the config. Don't worry if someone sees your firebase config object.

Can I hide my Firebase config?

You can't truly hide it because it needs to be in your frontend code for Firebase to work. Instead of trying to hide it, focus on writing proper security rules. The config is not a security credential.

What's the difference between Firestore rules and Realtime Database rules?

They use different syntax. Firestore rules use a match/allow syntax and can reference other documents. Realtime Database rules use JSON with .read/.write/.validate. Firestore rules are generally more flexible and powerful.

Should I validate data in my app or in security rules?

Both. Validate in your app for good UX (show errors immediately). Validate in security rules for actual security (server-side enforcement). Never skip rule validation because client-side code can be bypassed.

Check Your Firebase Security

Scan your Firebase project for insecure rules and misconfigurations.

Start Free Scan
Tool & Platform Guides

Firebase Security Guide: Firestore Rules and Authentication