Since I want to fetch data without authentication for my app, my security rules look like this:
{
"rules": {
".read": true,
".write": false
}
}
But Firebase said if someone has this URL he can fetch my data. How could I save my data. My app doesn't require authentication. How could I resist other, or what configuration I can set so only my app can fetch it.
In simple words,
No one should allow to fetch my app data(firestore) without my app. Where my app doesn't require authentication.
What you're asking for isn't possible. These things are all exactly the same:
Accessing data via client SDK without authentication
Accessing data with the REST API without an authentication token
Accessing data in any way without using the app itself
If you want to restrict data to your app only, you will need some form of authentication provided by Firebase Authentication.
You have to use firebase Anonymous Authentication, This authentication doesn't require user input like email, password, SSO, etc. You can just set the code inside a button to Get Started, So firebase will automatically create a userID for each user.
Related
I am using Firebase Realtime Database for chat functionality in my app. Now we are ready to launch our app so we should fix this issue. xxxx-xxxx-4458' has insecure rules. In official documentation and other places i have found only solution where we need to use firebase auth for validation, But our main database and login process works on our own server and we are using firebase realtime chat as only for chat purpose, so we are not using any firebase authentications so we are still not able to fix issues.
We've detected the following issue(s) with your security rules:
any user can read your entire database
any user can write to your entire database
So Is there is any other way to secure our database without using firebase authentications.
Our Firebase Implementations.
We are using our own server for all the user login,sessions and user data. User login and validate is perform by our own server. That's why we don't use firebase for any other app functions than Real time chat.
As we are not using firebase auth for user validation. It's not possible by us to secure realtime database. User login,registration,sessions,validations all perform by our own server and after validations from our own server then user can start sending message with realtime database.
Our current rules
{
"rules": {
".read": true,
".write": true
}
}
Question:
Are we already secured from outsider attack(non-app user). If no then how we can make our database secure in our scenario?.
Update: That's How my database arranged.
Now on successful login on our server, I am generating JWT and using it as
mAuth.signInWithCustomToken(mCustomToken)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
// Sign in success
} else {
// If sign in fails
Toast.makeText(CustomAuthActivity.this, "Authentication failed.",
}
}
});
I don't understand where/how to validate that token on firebase Auth. Please put insight on it.
With your current rules anyone in the world can wipe your database with a single API call. They can also read the entire database with a single API call. Neither of those are likely use-cases that your app requires, so I'd say your app is currently not secure.
If you want to properly secure access based on the user identity, you can inform Firebase Authentication of the profile of the user in your own identity system by implementing custom authentication. Once you have that implemented, the auth variable in your security rule will contain the information from your own user system, and you can then use that to secure access to the data.
Even if you know nothing about the user though, you can already secure your app better than what you currently have, by writing rules that fit your use-cases.
For example, since you have a chat app, you likely have a list of chat messages, and users append new messages to this list. Instead of saying that everyone can do whatever they want to the root of your database, you can only allow them to post chat messages with something like:
{
"rules": {
"chat": {
".read": true,
"$message_id": {
".write": true
}
}
}
}
So now, users can only read the /chat node, and they can only write specific nodes under it. Just this simple change already rules out a whole lot of abuse scenarios.
One step better, would be to validate that the chat messages are of the structure that you expect. For example, if the message have a user name, timestamp, and a text message, that could be:
{
"rules": {
"chat": {
".read": true,
"$message_id": {
".write": true,
".validate": "newData.hasChildren('name', 'timestamp', 'text')"
}
}
}
}
At this point you should note that these rules reflect some of your application code, which is normal: your security rules should only allow what your application code needs, and nothing more. This is known as the principle of least privilege, and is a common security practice.
Finally, you should probably also consider using Firebase App Check which can also prevent a lot of abuse by folks who are not using your application to access the database. Note that this is not a guarantee though, so you'll want to combine App Check for broad protection with security rules for fine-grained control.
Some more resources:
Firebase email saying my realtime database has insecure rules
Firebase says that my rules are insecure, why?
Issue with my Firebase realtime data base security rules
Firebase Rules Write Permissions
I have used Firebase Firestore for database storage. I had a scenario in which i need to manage users login and logout using phone number and OTP. and as Firebase authentication manages authentication using email id or if you want to use it with phone number every time you need to verify it using OTP which was not feasible for my application so, I created my own process of authentication in which I am using OTP authentication once and I store users data to the collection and then after when users login I directly check it from collection.
It is perfectly working now but as I am facing issues while changing security rules as I want to restrict user in reading database. But I don't know how to write it as I have found many solution till now but that all were having auth in request but as I am not using auth I may not have auth in request and could find it null.
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write : if true;
}
}
}
I have given read and write access to all the collection so, anyone having key can access db but I want to restrict it using security rules and I have kind of found a way of restricting user when creating or updating as I will be getting resource when requesting for set or update but in case of reading or getting data it might not have resources as i am not passing any data . So please help me if you know how can I write such rules. Thanks In Advance...
To allow only users that are authentication with Firebase access to data, you rules would be:
allow read, write: if request.auth.uid != null;
It isn't possible to do the same without Firebase Authentication, as the only way to pass data about the user into security rules is through Firebase Authentication.
If you have your own authentication mechanism, you can implement that as a custom provider within Firebase Authentication. In this approach you use server-side code to generate a Firebase token based on the information you have about the user, and the information from that token then becomes available in the security rules under auth.token.
I am trying to setup custom authentication with my firebase system, I am looking at this firebase link and this one. I noticed with this approach you need to send the users credentials to your server:
However, I have implemented our system in a different way - where when the user enters their display name the credentials are posted to the server, the db will check whether these credentials are stored in the db and only if they are then the encrypted password shall be sent back to the java class where it will be stored in a string and decryted.
The password will then be compared with the password entered, if they are correct I want to generate the custom auth token with this method
mAuth.signInWithCustomToken(mCustomToken)
and then allow the user to login. So basically in short I want to create the custom auth token in my java class which is part of the application.
P.S I am using firebase realtime db as my db
trying to build an Android and Web client that has Parse.com as a backend. User has to be authenticated first to log into the app. If someone gets hold of the Application keys, client keys etc. he can access the app without the authentication with Rest calls. How can this be avoided to restrict the Parse Query to return results ONLY with a user session? Looking for that security measure.
All the Parse Application and client keys (except for the master key) are considered public information and NOT secrets. This is clearly mentioned in the Parse documentation. There is no way to hide them and they will be part of your app/website and they can be easily retrieved by any user. This means any data in your classes with Public read access can be retrieved by anybody.
Parse lets you control the data read permissions ONLY via Class Level Permissions(CLPs) and Access Control Lists(ACLs). If you think these solutions cannot give you the security measures you are looking to implement, you have to disable the public read access to your data completely and implement your own Cloud Functions to retrieve the data from server. This way, you can test the user credentials, permissions, etc before returning any data.
Which of the following ways is better to allow user to login once and avoid logging in again on next app launch?
1) Store just UserID and then just every time fetch data from server and load profile? (Problem: userID can be manipulated in SharedPreferences so user can easily hijack other users identity)
2) Store username and password in SharedPreferences then just auth user on every app launch and get users data from server? (Is this safe enough? )
3) On first login from device - store deviceID in online database and store userID in SharedPreferences, then on every app launch compare deviceID's and if matches = Fetch data and login automatically or if not matching = request login again?
Is there any better way perhaps? I would like to avoid using SQLite as for my app I have no need for database, my app is online MySQL database related and it's constantly communicating with it rather than having local database.
You could also send back a large meaningless id (such as a GUID) from the server on login. The server would store it in a list of valid login credentials. Store it on the phone also and send it back to the server for authentication. There would be no way to forge an id since it cannot be derived from any other information, and the chances of guessing one would be miniscule.
1) and 2) should never be done as it compromises on the security and any one with read/write privileges can easily view the sensitive information.
3) could work but not with the device id since that can also be manipulated on rooting. I would suggest you use the userid+password+deviceid to generate a hash and store that in your database. Consequently whenever you make any calls to your server use this hash to authenticate the user.
About fetching the data you need not do it every time. If the data is not very sensitive you can store it in your shared preferences and use it to reduce the network calls. You can use this to show the screen which opens on first time usage and consequently fetch additional data by making a network request. It would also not interfere with the user experience