Restricting deletion permissions in Firestore - javascript

I have a node web app where I use Firebase for data storage, and I was wondering if there was a way from the Firebase console to add Rules to only allow creation and viewing of data on a certain database.
For example, in my app, I want users to be able to create a message and view messages, however I don't want them to ever be able to delete them.
Is there a way to restrict deletion of documents in Firestore rules?

You can break down write into more granular operations, as stated in the docs:
A read rule can be broken into get and list, while a write rule can be broken into create, update, and delete:
An example of your particular case:
service cloud.firestore {
match /databases/{database}/documents {
match /messages/{messageId} {
allow read, create, update: if request.auth.uid != null;
}
}
}

Related

How to safely query the users from a collection without the user reading or accessing other fields with sensitive data?

I am trying to make a Trello-inspired app using React and Firestore. I'm now doing the feature where users on the board will invite or add others users.
The problem is when users are looking for other users, it is done on the frontend. My security rule allows reading of the users collection if the user:
allow read: if request.auth != null
The part where I query the users, trying to see if the email address or name matched
try {
const matchedUsers = []
const queryUsers = query(
collection(db, 'users'),
where('nameArray', 'array-contains', matchedUser)
)
const querySnapshot = await getDocs(queryUsers)
querySnapshot.forEach((doc) => {
const userObj = {
id: doc.data().userId,
name: doc.data().name,
photo: doc.data().photo,
}
matchedUsers.push(userObj)
})
setUsers(matchedUsers)
} catch (err) {
console.log(err)
}
As you can see there, it seems like I'm letting other users read other users' documents in the collection which will be problematic because my user doc contains email address too. I'm thinking that anyone can change the frontend code and get the email address of other users. Is my security rule for reading the users collection wrong? Because I know that if a security rule allows access or allow reads, then the user will have access to the entire document.
I want to know the best practices for doing this. I am new to the backend or database, I am just a newbie trying to create personal projects.
I found a suggestion from firestore
Read only for specific fields but I have yet to try this
I'm thinking if I can do this, making the email a private subcollection since I only need the name or the userId. I really dunno if I'm doing the right thing or if my security rule request.auth != null is fine.
Is my security rule for reading the users collection wrong?
That is hard for us to say. Your security allows everyone who is signed in to Firebase Authentication to read all users (or whatever match you've defined that rules on).
If that is not what you want, you'll have to be explicit about who can read what data from your database, and implement that both in your JavaScript code and in your security rules.
For example, if you want to enforce where('nameArray', 'array-contains', matchedUser) on the server, you will have to find a way to implement it in your rules. For what you can do there, I recommend reading the documentation on securely querying data

Basic Firebase Rules [duplicate]

This question already has answers here:
stop Firestore warning that everyone can read data
(1 answer)
Your Cloud Firestore database has insecure: any user can read your entire database
(2 answers)
Closed 2 years ago.
I am new to firebase, and am a bit stuck with the rules.
My app is essentially a blog-site.
It allows non-logged in to read posts, users, comments.
It also allows logged-in and verified users to create a post.
Here are my rules
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read: if true;
allow write: if request.auth.uid != null;
}
}
}
Firebase sends me emails that these are not secure due to "any user can read your entire database".
Is there something I am missing? As I want people to be able to read the data without being logged in?
I believe you're still getting that due to, based on the "if true" logic, any user has the ability to read anyone else's "stuff." What you could do is add some functions within the match database documents that return more tailored tests. You really want to avoid an open database in Firestore, so part of that is by design, in-terms of that e-mail you're getting. I went through this same issue myself, and ended up moving over to Mongo for that particular use case.
However, if you want to keep it open, you can turn off the alert emails from the console. Click on Firebase alerts in the top-right, click settings (gear), select your project, just choose which you want to receive. I know those alerts can get annoying, haha, but it's Google's way of trying to help :) good luck!
Firebase prefers that you call out each collection individually in your security rules to allow access, rather than use a wildcard to match everything. They have no way of knowing if you actually have some private data in a collection and are accidentally giving access to it. By specifying rules for each collection separately, you are being very clear and specific about the access for each one of them.

Firebase storage rules error: unexpected identifier; function taken from documentation

I am using firebase and am trying to make the storage publicly accessible. According to the firebase documentation I need to include the following code, which I added to the .js file which contains a function that sends user input to storage.
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write;
}
}
}
Based off others' problems I've tried:
adding ;-s
changing it to firebase.storage(code),
doing var storage ...
but none of these methods work.
I have my code for configuring firebase (apiKey, authDomain, databaseURL, projectID, and storageBucket) and also initialized the app.
This isn't code that you would put in a JS file, this is a firebase storage security rule. It is a configuration that you would configure in the console for your project (alternatively, you can deploy the rules via the CLI, but they are still not a direct part of your application code).
You should navigate to the rules tab and input the configuration there:
Of course, the rule you are suggesting here is very dangerous!
This rule will allow any user (including unauthenticated users!) to write as much as they want into your storage bucket -- effectively giving you the bill for their free storage. You should consider carefully if this is what you really want.

How to properly implement firestore database rules to prevent update to data when certain field changed?

I am building a NodeJS Express app and am using Firebase as the backend. I am trying to secure my firebase backend, more specifically the firestore database with Firestore Security Rules. However, I cannot seem to get my security rules to trigger.
I have a route called /api/goalPRs/:goalPRId which updates a database ref with the body of the request by calling
const goalPRsRef = db.collection('goalProgressReports');
goalPRsRef.doc(goalPRId).update(newGoalPR).then(()=>({update: 'Success'}));
Now, each goalPR has a field called targetGoalId, which I want to be constant, I dont want that data to be editable. Hence I have tried to set up the following firestore security rule.
service cloud.firestore {
match /databases/{database}/documents {
match /goalProgressReports/{goalPR} {
allow update: if request.resource.data.targetGoalId == resource.data.targetGoalId;
}
}
}
With this security rule I expect that any update to a document within goalProgressReport collection should be denied if the old targetGoalId is not equal to the new one. However, this is not the case. I can provide a new targetGoalId and it incorrectly updates.
Also, even when I try something like this with the security rules:
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if false
}
}
}
I am still allowed to write to the database, even though from my understanding this rule shouldn't allow any reads or writes to the database. Is my understanding of how security rules work incorrect? How can I fix my goalProgressReport security rule to not allow updates if the targetGoalId has changed?
Since you're running on nodejs, that means you're using either the Cloud Firestore node SDK or the Firebase Admin SDK which wraps the Cloud SDK. In this case, security rules don't apply. They only apply to access coming directly from web and mobile applications, and not from the server SDKs. The server SDKs always bypass all security rules, because it's coming from a privileged service account.

Loading file from Firebase storage through selfLink gives 401

I am putting files in Firebase Storage, and (using cloud functions) store the objectMetaData.selflink in the database. I am trying to load a file using that link, but get a 401 stating that:
Anonymous users does not have storage.objects.get access to filename]
But since i am logged in (there is a currentUser on the auth() instance), i am confused what i am doing wrong here. Should i be sending some kind of token with my request?
I have not changed the initial ruleset for storage:
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if request.auth != null;
}
}
}
Also, maybe related but maybe not: since this example uses another approach, what is the difference between selfLink and getDownloadURL?
EDIT:
I finally got it working by using firebase.storage().ref(somePath). I also tried firebase.storage().refFromURL(selfLink).getDownloadURL() but that gave the error of supplying an invalid link to refFromURL. Then the question remains: what exactly is the selfLink?
Documentation states that the selfLink is the link to access the object, assuming you have sufficient permissions. It is not the download URL
Docs

Categories