Firebase storage and firestore database rules

What should the database and storage rules be so that each user can only read, write and upload their own files?

once you create a user with a UID you can give specific permissions in Firestore Database rules like this:

rules_version = ‘2’;

service cloud.firestore {
match /databases/{database}/documents {
// Replace this with your admin UID
function isAdmin() {
return request.auth != null && request.auth.uid == “UID”;
}

match /{document=**} {
  allow read, write: if isAdmin();
}

}
}

I have been experiencing the same issues with firebase on the rules, Migration of products to my database for my eccommerce site also fails as well. Any fixes on the rules
this has been the error
FirebaseError: Missing or insufficient permissions: The following request was denied by Firestore Security Rules:
{
“auth”: {
“uid”: “LBzvLb3OzQP7d1kTzOuNbZ2bUrg1”,
“token”: {
“name”: null,
“email”: “admin@example.com”,
“email_verified”: false,
“phone_number”: null,
“sub”: “LBzvLb3OzQP7d1kTzOuNbZ2bUrg1”,
“firebase”: {
“identities”: {
“password”: [
“admin@example.com”
]
},
“sign_in_provider”: “password”,
“tenant”: null
}
}
},
“method”: “list”,
“path”: “/databases/(default)/documents/orders where customerId == LBzvLb3OzQP7d1kTzOuNbZ2bUrg1”
}

Any help with this

Hello! This is the most fundamental and important security pattern in Firebase, and I’m happy to lay it out for you.

To make this work, you need to use the user’s unique ID (uid) from Firebase Authentication to “tag” their data in both Firestore and Storage.

Your rules will then check: “Is the authenticated user’s ID the same as the ID on the data they are trying to access?”

Here are the complete rules you’ll need.


:fire: Cloud Firestore Rules

For Firestore, the best practice is to add a userId field to every document that a user “owns.” Your rules will then check this field.

Copy and paste this into your firestore.rules file:

Code snippet

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

    // Match any collection (e.g., "posts", "notes", "userFiles")
    // where documents are owned by users.
    // This rule assumes you have a field called "userId" on each document.
    match /{collection}/{docId} {

      // A user must be logged in to do anything
      function isSignedIn() {
        return request.auth != null;
      }

      // Is the logged-in user the owner of this document?
      function isOwner() {
        // 'resource.data' checks the document *as it exists in the database*
        return request.auth.uid == resource.data.userId;
      }

      // Is the user *about to become* the owner of a new document?
      function isCreatingOwn() {
        // 'request.resource.data' checks the document *being sent* in the request
        return request.auth.uid == request.resource.data.userId;
      }

      // --- PERMISSIONS ---

      // CREATE: Allow if the user is signed in AND they are setting
      // the new document's 'userId' field to their own UID.
      allow create: if isSignedIn() && isCreatingOwn();

      // READ, UPDATE, DELETE: Allow if the user is the owner.
      allow read, update, delete: if isOwner();
    }
  }
}

:light_bulb: How to Use This in Your App (Crucial!)

  1. When a user creates a new document, you must add their UID to it in your client-side code:

    JavaScript

    // Example: Adding a new "note"
    import { collection, addDoc } from "firebase/firestore";
    import { auth, db } from "./firebaseConfig"; // Your exports
    
    const uid = auth.currentUser.uid;
    
    await addDoc(collection(db, "notes"), {
      title: "My New Note",
      content: "Hello world!",
      userId: uid  // <--- This is the field the rule checks
    });
    
    
  2. When a user reads their documents, your read rule requires you to fetch only their documents.

    JavaScript

    // Example: Getting all notes for the current user
    import { collection, query, where, getDocs } from "firebase/firestore";
    
    const uid = auth.currentUser.uid;
    
    // This query is now allowed by your security rules
    const q = query(
      collection(db, "notes"),
      where("userId", "==", uid) // <--- This query matches your rule
    );
    
    const querySnapshot = await getDocs(q);
    
    

:package: Cloud Storage Rules

For Storage, you can’t check fields on a file. Instead, you must use the file’s path to enforce ownership.

The best practice is to store each user’s files in a folder named after their uid.

  • Example Path: user_files/LBzvLb3OzQP7d1kTzOuNbZ2bUrg1/my-image.jpg

Copy and paste this into your storage.rules file:

Code snippet

rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {
  
    // Match any file inside a folder named after a user's UID
    // We use {userId} to capture that part of the path
    match /user_files/{userId}/{allPaths=**} {
    
      // Allow read, write (which includes upload/delete)
      // ONLY if the authenticated user's UID matches the {userId} in the path.
      allow read, write: if request.auth != null && 
                            request.auth.uid == userId;
    }
  }
}

:light_bulb: How to Use This in Your App (Crucial!)

When you upload or download files, you must build the path using the user’s UID in your client-side code.

JavaScript

// Example: Uploading a file
import { ref, uploadBytes } from "firebase/storage";
import { auth, storage } from "./firebaseConfig"; // Your exports

const uid = auth.currentUser.uid;
const file = /* ... your file object from an input ... */;
const fileName = file.name;

// This path matches your security rules
const storagePath = `user_files/${uid}/${fileName}`;
const storageRef = ref(storage, storagePath);

await uploadBytes(storageRef, file);