Get hands-on experience with 20+ free Google Cloud products and $300 in free credit for new customers.

Need a help related to Firestore Security Rules

Hi,

Let's say I have a collection called dogs and inside that have a list of documents like dogA, dogB, and so on. I need to give access to a web application to only read each document. But dogs collection should be locked. It is as follows.

/dogs/dogA  --> should be accessible
/dogs/dogB  --> should be accessible

/dogs --> should not be accessible

How can I achieve this using security rules?

Solved Solved
1 6 693
1 ACCEPTED SOLUTION

I apologize for the oversight. You're right; Firestore security rules doesn't seem to

have a specific list property.

The issue is that the read rule encompasses both get (retrieving a single document) and list (listing all documents in a collection). To differentiate between them, you should use the get and list properties explicitly.

Here's the correct way to set up the rules:

rules_version = '2';

service cloud.firestore {
match /databases/{database}/documents {
// Match any document inside the 'dogs' collection
match /dogs/{dogId} {
// Allow get access to individual documents
allow get: if true;
}

// Deny list access to the entire 'dogs' collection
match /dogs {
allow list: if false;
}
}
}

View solution in original post

6 REPLIES 6

You can achieve this using the following security rules:

rules_version = '2';

service cloud.firestore {
match /databases/{database}/documents {
match /dogs/{document=**} {
allow read: if true;
}
match /dogs {
allow read: if false;
}
}
}

This rule first sets the version of the security rules to 2. It then defines two match statements. The first match statement matches all documents in the dogs collection. The second match statement specifically targets the dogs collection itself.

The first match statement allows read access to all documents within the dogs collection. This means that the web application will be able to access individual documents like /dogs/dogA or /dogs/dogB.

However, the second match statement denies read access to the dogs collection as a whole. This ensures that the web application cannot list all the documents in the dogs collection or perform any operations on the collection directly.

In essence, this rule configuration allows the web application to read individual documents within the dogs collection but prevents it from accessing or listing the entire collection.

Hi @ms4446,

Thanks for the reply. However, I tried the way mentioned. But actually, it is not working. Here is the code I am using and the reply I got.


const start=async () => {
const docRef = doc(db, "dogs", "dogA");
const docSnap = await getDoc(docRef);

if (docSnap.exists()) {
console.log("Document data:", docSnap.data());
} else {
// docSnap.data() will be undefined in this case
console.log("No such document!");
}

console.log("--------------------------------")
console.log("--------------------------------")

const querySnapshot = await getDocs(collection(db, "dogs"));
querySnapshot.forEach((doc) => {
// doc.data() is never undefined for query doc snapshots
console.log(doc.id, " => ", doc.data());
});
};

 

Screenshot 2023-08-10 at 14.12.05.png

The code you provided is attempting to read a single document (dogA) from the dogs collection and then trying to list all documents in the dogs collection. 

he code should be able to read the individual document (dogA) but should fail when trying to list all documents in the dogs collection.

However, the problem is that the rule match /dogs/{document=**} { allow read: if true; } is too permissive. It's allowing read access to all documents and subcollections under /dogs, which inadvertently includes the collection itself.

To fix this, you should be more specific with your rules. Here's the corrected security rules:

rules_version = '2';

service cloud.firestore {
match /databases/{database}/documents {
// Match any document inside the 'dogs' collection
match /dogs/{dogId} {
// Allow read access to individual documents
allow read: if true;
}

// Deny list access to the entire 'dogs' collection
match /dogs {
allow list: if false;
}
}
}

@ms4446 

I’ve tried that way. But it is still the same. 😞
Also, I couldn't find any list property in the docs as well.

Screenshot 2023-08-10 at 21.35.20.png

I apologize for the oversight. You're right; Firestore security rules doesn't seem to

have a specific list property.

The issue is that the read rule encompasses both get (retrieving a single document) and list (listing all documents in a collection). To differentiate between them, you should use the get and list properties explicitly.

Here's the correct way to set up the rules:

rules_version = '2';

service cloud.firestore {
match /databases/{database}/documents {
// Match any document inside the 'dogs' collection
match /dogs/{dogId} {
// Allow get access to individual documents
allow get: if true;
}

// Deny list access to the entire 'dogs' collection
match /dogs {
allow list: if false;
}
}
}

Thank you @ms4446. It works that way. Also, thanks for the insights about the list property too 🙂