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! Go to 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;
}
}
}
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());
});
};
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.
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 🙂