All guidesVercel and env vars
On this page

Firebase question

My Firestore rules say allow read, write: if true. How do I lock them down before launch?

By Ohad Krispin, founder of VibeRaven · LinkedIn

Replace the rule before launch: allow read, write: if true on match /{document=**} lets anyone who guesses your project ID read, modify or delete every document, signed in or not, and Firebase's docs say never to use it in production. Start from rules that deny everything, then open each collection only as far as the app needs, usually to its owner with request.auth != null && request.auth.uid == userId. Test the new rules in the Rules Playground or the emulator, and publish them in the console or with firebase deploy --only firestore:rules. Rules apply to the web and mobile client libraries only: firebase-admin in your Next.js server code or Vercel functions bypasses them, so those routes need their own checks.

Where the open rule comes from

Creating a database in test mode starts with rules that, in Firebase's words, allow anyone to read and overwrite your data; production mode denies all reads and writes from mobile and web clients. If you manage rules with the Firebase CLI, they are in the file that firebase.json names, usually firestore.rules, and a CLI deploy overwrites the rules in the console. So check both: the file in the repo and the Rules tab, which shows what is live.

// Not for production: anyone can read and overwrite every document
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if true;
    }
  }
}

Rules that are still too open

Firebase's list of insecure rules has three more after open access. request.auth != null on everything lets any signed-in user read and write every document. A check on the email domain without request.auth.email_verified trusts an address nobody confirmed. And allow read: if true on a collection that holds private fields publishes those fields.

How long a change takes

Firebase says updated rules can take up to a minute to affect new queries and listeners, and up to 10 minutes to reach active listeners. Test with a fresh page load after publishing.

Checklist

Lock them down, test, then deploy

  1. 01
    Find the open rules in the repo, then compare with the Rules tab in the Firebase console:
    grep -rn "if true" firestore.rules
    grep -n "rules" firebase.json
  2. 02
    Replace the catch-all with one match per collection. Owner-only access, from Firebase's docs:
    rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
        match /users/{userId} {
          allow read, update, delete: if request.auth != null && request.auth.uid == userId;
          allow create: if request.auth != null;
        }
      }
    }
  3. 03For a collection that is public by design, allow read: if true and keep writes to the owner, comparing request.auth.uid with an owner field on the document. Delete the match /{document=**} block: when several matches apply, access is allowed if any of them allows it, so a leftover catch-all keeps everything open. Collections you do not list are then closed.
  4. 04If a rule checks the email domain, also require request.auth.email_verified.
  5. 05
    Test the rules before you deploy, in the console's Rules Playground or with the emulator and @firebase/rules-unit-testing:
    const testEnv = await initializeTestEnvironment({
      projectId: 'demo-rules-test',
      firestore: { rules: fs.readFileSync('firestore.rules', 'utf8') },
    })
    const alice = testEnv.authenticatedContext('alice').firestore()
    const anon = testEnv.unauthenticatedContext().firestore()
    await assertSucceeds(getDoc(doc(alice, 'users/alice')))
    await assertFails(getDoc(doc(alice, 'users/bob')))
    await assertFails(getDoc(doc(anon, 'users/alice')))
  6. 06
    Deploy from the repo, so the file and the console stay the same:
    firebase deploy --only firestore:rules
  7. 07Check your server code: firebase-admin in a Route Handler, Server Action or Vercel function bypasses the rules, so it must check the signed-in user itself before it reads or writes for them.
  8. 08Load the deployed app signed out and as a second user, and confirm the reads that should fail now fail with a permission error.

Related

Sources

Official docs behind this checklist

FAQ

FAQ for builders before launch

Is the Firebase config in my web app a secret?

No. Firebase's FAQ says its API keys are public by design: they identify your project and app, and access is controlled by IAM, Security Rules and App Check. So the rules have to protect the data, and Firebase suggests App Check on top, so that only your app's clients reach Firestore.

Can I keep allow read, write: if false?

Yes, if only your server reads and writes Firestore. Firebase's docs describe it as the setting for using Firestore as a server-only backend with the Admin SDK, which still has access; your browser code then gets permission errors.

Does request.auth != null make the data private?

Only from people without an account. Any signed-in user passes it, so add a condition on request.auth.uid, a role or an attribute for data that belongs to one user or team.