How to restrict users access to database in firebase firestore? - android

My requirement:
Total No of users:4
User1:Can submit his data. And if he pressed a button he can able see all 4users data.
Same like for other 3users also.
How can I achieve it?

You need to structure your database something like this:
users: {
userId1: {
...userData
}
}
Basically you need to separate data of each user in separate nodes.
Then use these security rules:
{
"rules": {
"users": {
"$uid": {
".write": "$uid === auth.uid"
".read": true
}
}
}
}
Now the user can write to his/her data only but everyone can read it.

you can use database security rules, https://firebase.google.com/docs/database/security/
and i suggest you structure your data in database like
/data/<userId> and limit the user write access to its userId
of course you also need to implement firebase auth.

Related

How to avoid firebase security warning and validate username while signup?

Am using the firebase database as my storage. While signing up am storing the username for validating the uniqueness of the username. I declared firebase security rules as follow,
{
"rules": {
".read": true,
".write": true
}
}
And my database structure is as follow,
Users
o**kcarw***27p**enV**UcB3***
Email: "testing#mail.com"
UserName: "GokulNew"
But if I declare as above am getting a firebase warning as "Your project's Realtime Database "Project" has insecure rules ".
So later I changed the security rules as follow,
{
"rules": {
".read": "auth !=null",
".write": "auth !=null"
}
}
If I declare as above the security warning is not showing but it is not allowing me to signup due to the security rules. So again I changed the rule as follow,
{
"rules": {
".read": "auth !=null",
".write": "auth !=null",
"Users":{
".read": true,
".write": true
}
}
}
After this, it is allowed me to signup but a security warning is showing. How can I avoid the security warning and at the same time I need to validate the username while signup.
And below is the Java code for signup
Query usernameQuery = FirebaseDatabase.getInstance().getReference().child("Users").
orderByChild("UserName").equalTo(upperCaseChar(username));
usernameQuery.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if (snapshot.getChildrenCount() > 0) {
usernameLayout.setError("Username is already taken");
vibrator.vibrate(VibrationEffect.createOneShot(200, VibrationEffect.DEFAULT_AMPLITUDE));
dialog.dismiss();
Toast.makeText(RegisterActivity.this, "Username is already taken, Choose new one", Toast.LENGTH_SHORT).show();
} else {
//sign-up and storing the data to firebase
}
}
}
Hope my requirement is clear and thanks in advance,
Your rules should follow the principle of least privilege, meaning they allow exactly what your code needs and nothing more. Since the code you shared performs a query on /Users, you want to secure for that query, which would look something like this:
...
"Users": {
".read": "query.orderByChild == 'UserName' &&
query.equalTo.length > 0"
}
...
This only allows (if it works, because I didn't test the length check) reads on /Users that query on UserNames and specify an equalTo value, so that matches your code.
I'd recommend considering another data structure for this though, as your current code may not work when multiple users try to claim the same name around the same time. To make that work, you should introduce a top-level node where you use the username as the key and then use a transaction to write there, and in security rules ensure a value can only be written if non exists yet.
For more on this, also see these previous questions about unique usernames.

I can write data but I can't read in Firebase

I'm new to firebase. I have a problem with firebase security rules. I can write data to the firebase database but I can't read the written data.
My database look like-
user|
|_uid(auto-generated)
|
|_name:Bob
|_score:100
|_email:bob#gmail.com
My firebase database rule look like-
"user":{
"$uid":{
"uname":{
".read":"$uid=== auth.uid",
".write":"$uid=== auth.uid"
},
"score":{
".read":"$uid=== auth.uid",
".write":false
},
"email":{
".read":"$uid=== auth.uid",
".write":"$uid=== auth.uid"
}
}}
I have tested with simulator and everything(both read and write) goes fine. But can't read from my app although I logged in to an account.
When I set all read and write to true upper $uid node, all read write from my app OK too. But I want to allow read to authorized person only
I have already searched on stackoverflow, but there is no solution for this.
Sorry for my English writing skill.
As you are using realtime database the best way to handle this is to create a child authorized and then save all authorized uid in this child and then set your rules as follows:`"rules":
{
".read": true,
".write": "root.child('authorized').hasChild(auth.uid)"
}
}`
you can refer to this project to see sample implementation
If you used push() when creating the uid inside user node then the authid and uid are not the same. They have different values.MAKE SURE YOU USED THE SAME UID FROM
firebaseauth.getinstance().getcurrentuser().getuid()
If you want to authorize people to only do something to only their data you can use the following set of Rules.
{
"rules": {
"user": {
"$uid": {
".read": "$uid === auth.uid",
".write": "$uid === auth.uid"
}
}
}
}
The node you have is name but the level indicated on the rules is uname...

How to query Firebase-DB for data like 'WHERE'-clause?

I'm working on a contact-app for android with firebase and I want to read values (here: the users' profile) from a user in my database that matches a specified email.
I tried to design the query like shown in this answer: https://stackoverflow.com/a/39025129/8739722 but the problem is that I don't know how to apply this to my database-structure since I have another child (profile) in my user-structure.
My Nodes look like this:
My Rules look like this:
{
"rules": {
"users": {
"$uid": {
"profile": {
".read": "auth.uid != null",
".write": "auth.uid == $uid",
},
//...
},
}
I tried to query like this:
String email = "email_address_1";
Query q_1 = ref.child("users").child("profile").orderByChild("email").equalTo(email);
...resulting in a 'permission denied' error.
I also considered following queries but they have invalid syntax or try to perform multiple orderByChild-calls which is not allowed:
String email = "email_address_1";
Query q_2 = ref.child("users").orderByChild("profile").child("email").equalTo(email);
Query q_3 = ref.child("users").orderByChild("profile").orderByChild("email").equalTo(email);
How can I get the profile-information of the user with the matching email?
Firebase Realtime Database queries filter and order on a single property that is under a fixed path/name under each child node of the location where you run the query. In your case the property is under profile/email, so your query becomes:
ref.child("users").orderByChild("profile/email").equalTo(email);
But note that your rules will reject this query, since they request to read data from /users and you don't grant anyone permission to read data from there. Firebase security rules are enforced when you attach a listener, and can't be used to filter data. To learn a lot more about this, read the documentation section called rules are not filters and the many questions mentioning that same phrase.
To quickly test the above query, you can temporarily grant every access to /users. Just be sure to change it back before sharing your app with any users.
To properly secure the data you'll need to verify in your security rules that the user is only trying to read their own data. You can do this with query based security rules. In your case they'd look something like this:
"users": {
".read": "auth.email != null &&
query.orderByChild == 'profile/email' &&
query.equalTo == auth.token.email"
}

Android Firebase Prevent User From Deleting Database

I am working on an android project that uses firebase as online database. I realize that on database there is some values, nodes that shouldn't be there. I think someone change apk file and modify some code and writes another field in my database. How can I prevent this? Because if they can write something to any field they can also delete all my data by simply writing to my main node setValue(something).
Use rules, a logged in user only have access to certain nodes
{
"rules": {
"users": {
"$uid": {
".read": "$uid === auth.uid",
".write": "$uid === auth.uid"
}
}
}
}
Start here
https://firebase.google.com/docs/database/security/quickstart

Firebase Android Banning Users

I have an android app that people can write something on chatbox.
They login with google account. And i have their user id which is shown below by $uid
But if there will somebody writing stupid things i want to prevent this person's writing ability.
So how can i make this by using this body. Or what is your suggestion?
{
"rules": {
"users": {
"$uid": {
".read": "$uid === auth.uid",
".write": "$uid === auth.uid"
}
}
}
}
source: https://firebase.google.com/docs/database/security/
Updated Answer
First, you have to change your banned user JSON model to follow format.
Path pattern
/banned-users/$userid: true
From above image
/banned-users/fasjdkflksdflad: true
now change your rules to the following way
{
"rules": {
"messages": {
"$messageId": {
".read": "auth.uid != null",
".write": "auth.uid != null && !root.child('/banned-users/'+auth.uid).exists()"
}
},
}
}
Say you are adding messages to the /messages path with each messages id as $messagesId then your /messages path looks like below
{
"messages": {
"-KTKvywjwDv4RpYjQglu":{
"text": "Hey Guys..."
},
"-KTKvywjwDv4RpYjQglu":{
"text": "How you doing ..."
}
}
}
Explanation
According to the rules, any logged in user can read the /messages ".read": "auth.uid != null", defines that.
To write to message to /messages path, then firebase check for if the (user is logged in AND /banned-users/user-id path exists) in firebase. As auth.uid is internal firebase variable used when rule validation. ".write": "auth.uid != null && !root.child('/banned-users/'+auth.uid).exists()" defines that.
you can ignore .validate you can achieve this by just using .write.
old answer
You cannot do it with just security rules.
First, you have to use Firebase cloud functions.
Create database trigger on the /chats database path. When the new message contains stupid things then you can delete it right away and you can get the user ID and save it to some other path say /banned-users/<userid>
Now you can write the .validate rule to check current messaging userid is not on the banned list. Using
".validate": "!root.child('/banned-users/'+$uid).exists()"
If you have to completely disable user account then you have to use Firebase Admin API.
You do not need to do this in rules. You can just disable that person's userID in the "Authentication" section of the FirebaseConsole
Screenshot attached below as sample
This would be much easier compared to adding into the rules where you have to enter the userID manually anyway.

Categories

Resources