In my app each user has a "balance" entry in Firestore that handles their in-app credits.
How can I update in a secure way their balances when they interact with the app?
At the moment I update the balance client-side, with Firestore.collectio().document().update({...}) but I'm not sure if that is enough safe, even if I have Firestore rules and AppCheck enabled.
To avoid problems, the ideal is that you make this update using a transaction.
Remembering that it is good to avoid numbers with floating point, in case these credits are money.
If you want to allow only certain updates to the balance, you can usually enforce those in your security rules.
If you've tried that and can't get it to work, we can help better if you show what you tried.
Related
now I am learning flutter for chat app, I need to get currentUserEmail, now I have two ways to save currentUserEmail, a. save it in sharedPreference; b. always get it from FirebaseAuth
So here is my question:
does FirebaseAuth.instance.currentUser.email Flutter count to one time read from firesbase(since currentUserEmail value will be used multiple times in my app, it may increase the cost)
is it safe to get currentUserEmail and then save it in sharedPreference, so in the future I can easily get this currentUserEmail from sharedPreference instead of always get this from FirebaseAuth. I am afraid hacker can change this currentUserEmail value locally, so the app may treat this user as someone else.
thank you for any info in advance and keep safe!
Regarding reading data from your Firestore and whether it'll affect the cost of using Firebase, a similar question was answered there:
https://stackoverflow.com/a/52701789/3213173
https://medium.com/firebase-tips-tricks/how-to-drastically-reduce-the-number-of-reads-when-no-documents-are-changed-in-firestore-8760e2f25e9e
So a short answer is - yes, it may affect, but you can reduce the cost by implementing solutions from the linked articles.
Regarding saving the user's email in the preferences - yes, you can save it as long as the authentication in your application doesn't rely on the email address only. If you're using any Authentication service (such as Firebase Auth), then changing email in the preferences won't cause any issues with user's authentication.
There is no need to cache the values of FirebaseAuth.instance.currentUser in sharedPreference yourself, as the Firebase SDK already caches this value for you. There is no cost for accessing FirebaseAuth.instance.currentUser or any of its properties.
Hope you guys are all doing well. I just have a quick question regarding Firebase and how if Firebase has any sort of ways to detect malicious users?
The scenario I am imagining is that some user downloaded my app and for whatever reason wrote some script or something that just continuously reads and writes to my Firebase firestore and/or storage
I am wondering if Firebase has any built in functionality that detects any unusual amounts of read/writes from a single user or what are some ways I can do so to prevent a user from, say, read and/or write more than 100 times within 1 min?
Thanks
Firebase doesn't have any per-user accounting. If you want to record what each user is doing and enforce limits, you'll have to implement that yourself. Security rules also will be of little help to you enforcing overall read limits. You will have to:
Force all users to access the database through a backend you control
Send the identity of the user along with the request
Record somewhere how much that user has read and written
Refuse to perform more queries if that limit is exceeded, for whatever threshold or duration you define.
In short, it's a lot of work you have to do yourself.
I am creating a react native application using Firestore and I am not sure how to implement secure schema validation on document creation and update.
If I understand security rules, it is possible to:
Limit who can perform operations (update, read, write, etc.) on documents
Limit operations allowed based on field conditionals
Limit operations allowed based on custom functions (post w/ examples)
My concern is that because of the client side nature of the requests, a savvy user could utilize their authentication and some client side code to .set() any field or map/object to any value they want unless a security rule prevents it. It appears I could use very complicated custom functions to validate the data received. I could also validate every update and create through a Cloud Function API, but I am attempting to use the Firestore database itself whenever possible.
Am I right to be concerned about the potential for users to abuse their .set() field creation abilities on authorized documents (i.e. documents with minimal userId rules)?
Is there an accepted way to create security rules that prevent client abuse of documents that don't have custom functions that validate the schema?
You should always consider malicious users, and how they might affect your data, no matter whether you write the validation in security rules or in more traditional code in Cloud Functions.
Compare these two statements from your question:
"I could use very complicated custom functions to validate the data received"
"I could also validate every update and create through a Cloud Function API"
In both cases you're writing custom code to ensure the data the user enters is valid according to your business rules. Since these rules are specific to your business, there's no way to prevent you having to write them. The only difference is where you write these business rules. With Cloud Functions you're writing the validations in regular JavaScript code, in an environment you may already be familiar with. With security rules you're writing the validations in a domain-specific language, which you'll have to learn.
I personally far prefer writing my business rules into Firestore's server-side security rule language, and then use Cloud Functions for implementing business logic on top of that validated data.
If you are worried that user might just reverse engineer your app and mess up your code to harm your database, then yes this is possible. You should have proper rules set. Talking of updating data in database from app, try to update it through cloud functions as far as possible. This way you might need to give less access to your users to the database directly.
You can check my answer here. This will help you setting rules and some ways to code adapt your app code based on situation. The answer also has some lines on where can one use cloud functions to reduce direct contact with the database.
And if there is no know or you feel the information should be directly updated to the database, change your rules to this: ".write": "$uid === auth.uid" .
Here $uid is name of parent node and can be anything else. This way a user can access his/her data only and even if the user modifies your app, they can harm their data only. (You should have correct rules set).
You can check out this link for most of the rules combinations.
And do check the answer whose link is above. That might clarify how it will secure your database to some extent. If you can provide any particular situation regarding your app and want some information for how to set rules there, feel free to drop a comment :-)
Firebase Firestore authenticated user write data freely after tampering code, is it possible?
For example, after setting firebase security rule to only allow user write document created by themselves, can hacker tampering the client side code and upVote their own post voteCount from 1 to 1000?
I understand we can set security rule to only allow increment of 1 vote per one write of document. I want to focusing on knowing whether hacker can modified client side code and use the app again as usual. A high confident answer is greatly appreciated. Thank you. I am a happy firebase user
For security purposes, you should assume that the client code has been compromised. After all, it's running on a machine or device that you don't have control over. It's actually pretty easy for someone to change the way JavaScript works in a browser environment.
Firebase has many security and data validation features in its rules system. All security and data verification needs to be done or verified within firebase rules. You can never trust that a client app/web-interface is behaving.
Perhaps votes are stored as a set of user-id: vote, and a user is only allowed to create a slot with their own id, and vote can be 1,-1 for example.
My users can create documents (let's say tasks) in a subcollection with a bunch of security rules checking for authentication, permissions and data validity. They can even select multiple tasks and copy them in the same collection.
Now, a regular user will likely create at most a hundred tasks at once, but what if someone with bad intentions manage to obtain my database credentials, authenticate and try to create a huge number of valid documents programmatically? This will result in Firestore scaling without problems and an unexpected surprise in my Firebase billing.
This is my first concern, but I'm also thinking about the possibility to limit a collection size for other reasons, and it would be at the same time a solution for the problem described.
I read about techniques to count documents in a collection described in the Firestore documentation, but I did not found a solution.
Keeping a counter on a doc field updated with a transaction in a cloud function would be inefficient in my case. Distributed counters increase the complexity of my data model a bit, and also I would not know how to properly read those counters in security rules for every task creation, and even if that would be an efficient solution.
Does anyone has suggestions?
I believe the way for a person to gain read/write access to your database would be to either to hack Google servers, in which case no one is safe and it doesn't really matter what you do, or to guess the exact name of your collections and documents.
As for the latter case, what I have done in my project is that for each collection and document I have used the name I wanted plus random 10-char Strings (including all kinds of chars and numbers. For example Users-x5NfaS1jCb) which kind of serve as independent, separate passwords every step of the way. This, at least, makes it difficult to guess the name of the collections and documents.
(Just like mentioned in the question) If using authentication does not cause any complications for you project, you can use it to further raise the security of your database by limiting access to users authenticating through your app only.
I guess (have never tried it) you can make use of Firebase Functions to limit the number of documents available in any given collection based on the criteria you want. This function will be invoked every time an event in created in the database.
If by "obtain my database credentials", you mean finding the username and password to your Firebase account, well it doesn't really matter what you do again. If they know what they are doing, they can take so many advantages that this particular issue will be the least of your problems.
All in all, if you ask me, your database is safe unless either someone guesses your collection and document names, or gains access to your Firebase account.
These are the only things I can think of for now. I'll try to update my answer later.