I'm building a simple game with a high score list containing user's name and score. I really wouldn't like to use any login or authentication, as the game is very simple and I just want people to be able to play it fast without a hassle. What's my best option to "secure" the real time database, as I need to allow user to read and write to database in order the game to work? I'm using the free tier of Firebase and my main concern is that someone could exceed my limits on purpose.
I would recommend the Anonymous authentication feature of Firebase, which assigns a unique 28-character string as the UID of each visitor. I believe the UID persists between site visits by default.
Then you can use database rules to secure your database. Here's an example database.rules.json that would:
Allow anyone to read from a particular location /games/$gameName/$uid (and child nodes)
Only allows the authenticated player to write to /games/$gameName/$uid/$gameNumber/ (and child nodes) and not allow data to be overwritten
Allow the authenticated player to write only a string value of length 1 to /games/$gameName/$uid/$gameNumber/gameComplete
The last point could be helpful for controlling the size of writes to not exceed your limit. But also keep in mind that the free Spark plan will simply stop functioning if you go beyond your limit. You will not suddenly incur costs unless you have upgraded to Blaze plan which requires a credit card.
N.B. The $ notation for wildcard key names in the database.
{
"rules": {
"games": {
"$gameName": {
"$uid": {
".read": true,
"$gameNumber": {
".write": "$uid === auth.uid && !data.exists()",
"gameComplete": {
".write": "newData.isString() && newData.val().length === 1"
}
},
}
}
}
}
}
You're going to need some access rules once you deploy the app. Otherwise, someone can delete your entire database with a single request. It's not difficult to implement a basic authentication system in Firebase - that's one of the main selling points of using Firebase in the first place. The easiest to setup is anonymous, then social auth, followed by email link auth.
https://firebase.google.com/docs/rules/insecure-rules
Securing the database doesn't necessarily mean that you need to ask your users for sign-in credentials. For example, if you use Firebase Authentication's anonymous sign-in, each user gets a unique, non-spoofable UID that you can use to secure access in security rules without them ever entering credentials.
Related
I have a React app which I developed for my own usage in localhost development mode.
The app stores some data to a firebase realtime database which I created just for the project.
Has no authentication, since only I use it in development mode.
The rules on the firebase database are the default ones:
{
"rules": {
".read": true,
".write": true
}
}
Thus firebase alerts me to the usual: 'Your security rules are defined as public, so anyone can steal, modify...' - warning.
My understanding is that in this case, the only way someone could get access to my data is if they got hold of information about the firebase instance, such as apiKey, database URL, authDomain. Is this true? (Or is there some other straightforward way people can get access to the data in this case, obviously not talking about hacking my computer/google account, etc.
This data is important to me, so basically I am wondering if my current practice is secure.
PS: I do understand how to set up firebase database security for a 'normal' user app. However, in this particular instance, I believe it is not needed, is this correct?
Thanks very much.
Anyone who knows the URL to your project can now read, and write your data. They can delete your entire database with a single command. While this may be exactly what you want (which is why Firebase allows it), most applications need more controlled access to their data (which is why you get alerts from Firebase to that effect).
Your best option is to add Firebase Authentication to your app. With that you can ensure that you are indeed the only person using it. Right now your statement about that is an assumption based on your faith in nobody having access to your URL. By implementing authentication, you can actually ensure that you're the only person having access to the data.
This could be as simple as implementing anonymous authentication, which generates an ID for the user without requiring them to provide any credentials. If you then log that ID, you can restrict access to the database to that one user with rules like this:
{
"rules": {
".read": "auth.uid === 'your_uid''",
".write": "auth.uid === 'your_uid''"
}
}
Even that simple change already makes your database much more secure, as now only that one user can access the data.
I strongly recommend that you spend some time reading more about Firebase's security model and rules, and that you then secure your database. Not only will this get rid of the alert, but (more importantly) it ensures the data is only accessed in ways that you control.
Using API key, database URL, auth Domain and etc, your end application makes a connection with the server. In short, all your API keys, database URL, auth Domain and etc are openly available. But this is not a problem until and unless your security rules are in place to protect your data from getting explored. Read more about Security Rules.
There are a few simple steps to protect or secure your data: [These are tips from me]
Use Authentication: This is the easiest way of keeping track of the user and the data the user can access or modify.
Note: Never trust the data coming from the user. You must validation the each and every data coming from the user.
Use of Functions: Functions have a special property - They can bypass the security rules. Remember not to expose all the data to users/open world. You can send the data to the invoked functions and let all the functions handle all the logic. This method is costly from the financial and request/response view.
So if I have an E-commerce App that doesn't require Login/Auth, and my users buy in the store, then after verifying the transaction the backend writes the order in the database.
The thing is that my Realtime Database just relies on Stripe transaction key (i.e, someone has paid for an item) to be able to write on the DB, because my rules are set so anyone can write, otherwise I would need every user to log in, but that's not what I want.
Firebase recently notified me that my rules are weak.
How can a make sure my users are able to write to my database in a secure way for my app, without log in/Auth?
There are many different security models you can use with Firebase, and it's important to understand the level of security each provides.
One thing to look into is anonymous auth which lets you "authenticate" a user without actually requiring them to provide any credentials. This provides a way to guarantee that the same device is being used between multiple reads/writes.
In your specific case, it sounds like you might be looking to rely on unguessable tokens. This can be a valid security model for some use cases so long as the key is sufficiently complex as to be unguessable.
At its most basic, the way you'd structure security rules for unguessable URLs is something like:
{
"rules": {
"transactions": {
"$key": {
".read": true,
".write": true
}
}
}
}
This allows users to read/write specific nodes at e.g. transactions/abc123xyzunguessable but importantly does not allow reading/writing to the parent transactions node. Security comes from the fact that only the person who originally got the unguessable token will be able to provide it again in the future.
A better implementation would gate writing on the $key matching the expected unguessable format, adding validation and other read/write rules to ensure that the data is formatted appropriately, and probably also prevent modification of key fields.
These are just some pointers but should help you on your way. The important thing is to make sure that you never leave important information in a place where it can be read through easily guessable URLs.
There is no "secure" way to allow writes to Realtime Database without Firebase Authentication. Without Firebase Auth, either there is full public access, or there is no public access at all.
If you can't use Firebase Auth, what you will need to do instead is make your security rules disallow all direct access to the database from client applications, then create backend APIs to manage access to the database. Your backend APIs will need to somehow validate that the person making the request should have the ability to make the required changes. Then, it will have to use the Firebase Admin SDK to commit those changes to the database.
I'm working on a PoC (Proof of Concept) application that users can download wallpapers to their device. All of the data is served using Cloud Firestore & Storage.
There is NO LOGIN for this application. Anybody can download the application, and immediately download the wallpapers she or he desires.
Bearing that in mind... I would like to have a counter that tracks how many times each specific wallpaper was downloaded.
While I have it "working" - I am questioning the rules I have set up in Firebase..
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read;
allow write: if request.auth != null;
allow update: if request.resource.data.counter is number;
}
}
}
My thought process with the rules above:
Anybody can read.
Only authenticated users can write. (I am managing all of the data with a headless CMS; Flamelink; so the 1 and only authenticated user is myself.)
Update the counter if the data is a number..
It's that last rule that I am questioning.
Is this a safe method of security to deploy to production?
Again - no login for this application, users can download all of the wallpapers with no authentication, and there will be a counter next to each wallpaper for users to see how many times each wallpaper has been downloaded.
The rules are not "secure" by any normal definition of that word. Here's what they allow. Anyone with an internet connection who knows the name of the project (which is easy to get) can:
Query for any document in the database
Update any existing document with any numeric value for counter in any document (it doesn't even have to increment, or be a positive integer)
On top of that, anyone who is able to get their Firebase Auth ID token (again, not terribly difficult for determined attacker), can fully create and write any document in the database. If you say there is no Auth at all in your app, then this is not really an issue, but if your project is configured to allow any form of authentication, it would be possible for an attacker to start writing anything.
You will get email from Firebase saying that your rules are not secure, mostly because you're allowing everyone to read everything.
What you should do is define more specifically what your security requirements are, then translate those into rules that actually meet those requirements. If you want to allow unauthenticated write access to your database of any kind, you are in a bit of trouble, as there is no way to make sure that the access actually matches the download behavior you're trying to measure. You'll be better off counting the downloads in whatever process manages the download, which is probably going to require a more sophisticated backend than what you have now.
But if allowing public read/write access is indeed what you want to allow, you'll be better off by making your rules more specific. For example, you can limit which collection the anonymous user can write to, and making sure they can only ever increment the counter, if these are the things you want.
I'm starting with firebase and i've a very basic question
in firebase rules for database i've:
{
"rules": {
".read": true,
".write": true
}
}
According to google it means that anyone can read and write on database.
My question is who anyone?
Let me clarify:
I don't want to force the user of my app to login, nor to have an account on google in order to use it.
this project is not shared with other people, other apps or any other stuff
is it possible to somebody to access the data stored in firebase? if yes how?
again if yes, what should i do to protect the data without forcing users to have credentials?
true here mean there is literally no protection of your data. Anyone who has the tools, and the name of your Firebase project, is able to fully read and write all your data. It should be considered that your database has extreme privacy concerns, which is especially bad for the data you're storing about your users.
Anyone can use something as simple as the REST API to access your entire database (or delete your entire database) with one request.
Without Firebase Auth, you should restict all access through some other protected API that you control. It's outside the scope of this question to fully explore how to set up that other API.
Referring to:
{
"rules": {
".read": true,
".write": true
}
}
You can imagine that the boolean value for the read and write as a security gate where true is open access and false is dead end. By stating it "true" means that people could just access your database (somehow) without even using your app.
Your points are:
This app is only for private used.
This app will not and never be distribute to other non-relevant people.
But, how do you make sure other people won't attack/ access your database? People could still access your database through browser controls (JS, Angular etc.).
Do remember, reverse engineering is possible, they could obtain your database information as well as your firebase credential JSON file, which could make your data in risk.
No matter what, it is advisable you restrict the security rules. My recommendation is to implement a simple role based security rule to prevent abusive and unauthorised API call usage.
It dawned on me that with so much client side logic, malicious users can spoof, override or game firebase apps by using the console in any browser.
For instance, I can enter $(".flag").click() and with three strokes flag every post out of existence on my app.
Any defensive logic I write will all be available to anyone who wants to crack it.
How have you dealt with this? Is there a work around?
In reality, Firebase is no different than any other server process with regards to security. Anybody can open the JavaScript console on any site (or write their own HTML page, or run curl from the command line) to try to manipulate data.
Firebase moderates clients using straightforward but surprisingly powerful security rules. Couple those with an authentication schema, and you can restrict access to, and validate any incoming data with minimal fuss.
{
"rules": {
// widgetName must be a string
"widgetName: { ".validate": "newData.isString()" },
// user accounts can only be read by the authenticated client
"users": {
"$user_id": {
".read": "$user_id === auth.id"
}
}
}
}
Firebase rules is really a new web building approach. You can build any kind of web app using thoses rules.
I'll not put rules code here but I'll explain what I mean.
For example. You want to build a learning app. using rules you can create two or three roles for users. Then for each content you can put a field(array for example) and check for each request if the requester user after authentication have the role to access some content.
I think all CMS are working by this way right now.
Hope this will give more ideas on Firebase platform.