Can't write to Firebase after changing rules - android

Using the default rules for writing to my real-time database:
{
"rules": {
".read": "true",
".write": "true"
}
}
I am able to successfully save data to the database:
The code from my Android app looked like this:
DatabaseReference mDatabaseReference;
mDatabaseReference = DatabaseReference.getInstance().getReference();
...
mDatabaseReference.child("user").child(user.getUid()).setValue(user);
But to allow signed in users (email and password auth) to access only their own data, I found this Firebase - How to write/read data per user after authentication. The answer uses a class Firebase that I can't seem to find anywhere. So I changed the rules to this:
{
"rules": {
"users": {
"$uid": {
".write": "$uid === auth.uid",
".read": "$uid === auth.uid"
}
}
}
}
with a little modification to my java code:
DatabaseReference mDatabaseReference, databaseReference;
...
mDatabaseReference = FirebaseDatabase.getInstance().getReference();
databaseReference = mDatabaseReference.child("user");
...
databaseReference.setValue(user); //user is a POJO
After deleting the old entries in my database and re-running my app, nothing happens when I try to save a new user.What am I missing?

In your rules, change users to user.
The name of the child in your Firebase rules
must match the name of the child in your java code.
Images added for clarity

Related

Firebase permission denied when attempting to load only records tagged as "public"

My rules look like this:
{
"rules": {
"userShaders": {
"$uid": {
"shaders": {
".write": "auth.uid === $uid",
".read": "auth.uid === $uid || data.child('public').val() == true"
}
}
}
}
}
My data looks like this:
userShaders
8v4N3yLlXAU1cpRiaDj5kkDQaKn1
shaders
myShaderName
attr_1: ""
attr_2: ""
public: false
I am not logged in as this user and am attempting to query their data. I expect to succesfully get back 0 records because they have none marked as public.
However, I'm getting a permission denied error.
My query looks like this:
val shaderRef = db
.getReference("userShaders/${uid}/shaders")
.orderByChild("public")
.equalTo(true);
shaderRef.get().addOnSuccessListener {
// do something with the data
}
To summarize, I am trying to query for only public data, while simultaneously making a rule that non-public data is impossible to fetch by other users. I want to write a query such that I may receive 0 or many records back, but never a permission denied error.
The most important thing to realize is that Firebase security rules don't filer data. Instead they merely check that you're only requesting data you are authorized for.
Your code already queries only for the public data, so you need to validate that query in your rules with something like:
"shaders": {
".read": "query.orderByChild === 'public' &&
query.equalTo === true"
}
Even with that you will still need separate read operations for the shared that this user created and all public shaders, as there's no way to express that OR condition in a single query.
Well, I ended up just separating my data into separate public and private sections in Firebase like this:
"userShaders": {
"$uid": {
"shaders": {
"public": {
".write": "auth.uid === $uid",
".read": "true"
},
"private": {
".write": "auth.uid === $uid",
".read": "auth.uid === $uid"
},
}
}
}
It's more work, because when I update the isPrivate boolean I have to make sure to delete it from the other section, but it does get the job done.
Open to other answers if there's another way to do this.

Write and Read in Firebase Android

I am using Firebase Realtime database with the below rules
{
"rules": {
"users": {
"$uid": {
".read": "$uid === auth.uid",
".write": "$uid === auth.uid"
}
}
}
}
My code to write in database is
mDatabase = FirebaseDatabase.getInstance().getReference("OWNER_DATA");
String id = mDatabase.push().getKey();
OwnerSignup ownerSignup = new OwnerSignup(id, name, email, phoneNumber);
mDatabase.child("MY_DATA").setValue(ownerSignup);
If I change the rules to
read:"false"
write:"false"
I can push the data but with the above rules I cannot insert values in the data.
Please help me to resolve this issue.
and how can I call this with API in Postman where my API is
"https://rent-c-246c0.firebaseio.com/"
I tried to do this in postman with the below given API
https://rent-c-246c0.firebaseio.com/OWNER_DATA.json
here I want to pass my auth.uid token
If you use the following rules:
read:"false" and write:"false"
It means you cannot retrieve nor add data to the database.
If you use:
{
"rules": {
"some_path": {
"$uid": {
// Allow only authenticated content owners access to their data
".read": "request.auth.uid == uid"
".write": "request.auth.uid == uid"
}
}
}
}
Then these rules restrict access to the authenticated owner of the content only. The data is only readable and writable by one user, and the data path contains the user's ID.
https://firebase.google.com/docs/rules/basics#content-owner_only_access

How to make firebase Realtime database user's private node?

I'm the Android app developer, and I'm using Firebase Realtime Database. I want to make an app that when users who want to use my app can save something like the text in their repository. But when I save the text in my app, other users who download my app can see my unique saved text. Firebase Realtime Database rules like this. But they didn't work. Please tell me how to use private node in Realtime Database.
{
"rules": {
"messages": {
"$user" : {
".read" : "$user === auth.uid",
".write" : "$user === auth.uid"
}
}
}
}
enter image description here
You also need to check if the auth rules are null. If yes, then not allow anyone to access the information. Also, you need to use a wildcard, instead of a static $uid value. So, put this inside the messages node. So, as you want people to write in the messages node, but only those who are owners to see the message, this is the code for it:
{
"rules": {
"messages": {
"${uid}": {
".read": "auth.uid != null",
".write": "auth.uid != null && auth.uid == uid"
}
}
}
}
I think the rules below do the trick. The codes snippet:auth.uid == $uid makes sure that only the owner of the node has writing rights while auth != null makes sure that only users logged in to your app can read from it.
{
"rules": {
"messages": {
"$uid" : {
".read" : "auth != null",
".write" : "auth.uid == $uid"
}
}
}
}
Another StackOverflow Question may also be useful for you if the situation becomes a little more complex.

Permission denied when writing data in firebase database

I'm developing one small demo project which uses Firebase Auth and Database.
I have the following rule configured for my firebase database
{
"rules": {
"users": {
"$uid": {
".read": "$uid === auth.uid",
".write": "$uid === auth.uid"
}
}
Through this rule, I want an authenticated user to have a read and write access for their data only.
Below is the java code which is trying to save data.
DatabaseReference databaseReference= FirebaseDatabase.getInstance().getReference().child(FirebaseAuth.getInstance().getCurrentUser().getUid()).child("basic");
{
DemoModel demoModel=new DemoModel();
demoModel.setId(databaseReference.push().getKey());
demoModel.setUser("demoUser"); databaseReference.child(demoModel.getId()).setValue(demoModel).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if(task.isSuccessful()){
Toast.makeText(DemoActivity.this, Constants.SUCCESSFUL, Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(DemoActivity.this, Constants.FAILED, Toast.LENGTH_SHORT).show();
}
}
});
}
Error I'm getting: W/RepoOperation: setValue at /xgjCUqcasda444WkgZFHTNRUB3/basic/-Lywe44rft566hhyYYfDS failed: DatabaseError: Permission denied
W/DynamiteModule: Local module descriptor class for com.google.firebase.auth not found.
My database looks like:
demoProject-dd4568
xgjCUqcasda444WkgZFHTNRUB3
-basic
-LE3gdfdffdfaza
id:"-LE3gdfdffdfaza"
user: "asdasd"
Where I'm going wrong. I don't have much clue. when I change the rule to
{
"rules": {
".read":"auth != null",
".write":"auth != null"
}
}
it works fine. but it's not secure then.
Your rules don't match your database structure at all. Your rules are protecting child nodes under users, but you don't have a users node in your database.
You should probably be changing the location of the write to include users in the path.
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference root = FirebaseDatabase.getInstance().getReference();
//providing uid
DatabaseReference ref = root.child("users").child(uid).child("basic");

Creating a new object in Firebase on Android

Following the official documentation, I want to store a new object (an instance of my Order class) on Firebase, and I want it to create a new key for me. This is what I'm doing:
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference orders = database.getReference("orders");
orders.push().setValue(order);
But nothing shows up from the console. Do I need to create the orders key in advance? I cannot create if manually from the console, because it appears that empty keys aren't valid.
The Order class is as follows:
public class Order {
private final ArrayList<OrderItem> orderItems = new ArrayList<>();
public ArrayList<OrderItem> getOrderItems() {
return orderItems;
}
public void addOrderItem(OrderItem orderItem) {
orderItems.add(orderItem);
}
}
Edit
Based on the comments, I checked the error I get:
Permission denied
But my access rules are:
{
"rules": {
"users": {
"$uid": {
".read": "$uid === auth.uid",
".write": "$uid === auth.uid"
}
}
}
}
So the rule should apply only to the users key, not to the orders one. For other keys, the default rules should apply:
The default rules require Authentication. They allow full read and write access to authenticated users of your app.
My user is authenticated, so why this is not working in my case? How can I ensure that the user is authenticated properly?
In any case, changing the access rules to:
{
"rules": {
"orders": {
".read": "auth != null",
".write": "auth != null"
},
"users": {
"$uid": {
".read": "$uid === auth.uid",
".write": "$uid === auth.uid"
}
}
}
}
Doesn't solve the problem.
Firebase does not support serializing Arraylists. You should use a List or Map instead.
The support Datatypes are:
String
Long
Double
Boolean
Map<String, Object>
List<Object>
You are confusing the default rules for your Database with the default rules that apply to a certain access:
Note: Access is disallowed by default. If no .write or .read rule is specified at or above a path, access will be denied.
Offical Firebase Documentation
To check if the user is signed in you can use this code snippet from the Docs:
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if (user != null) {
// User is signed in
} else {
// No user is signed in
}
Or you can use a listener to get informed about changes with the AuthState:
mAuthListener = new FirebaseAuth.AuthStateListener() {
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth) {
FirebaseUser user = firebaseAuth.getCurrentUser();
if (user != null) {
// User is signed in
Log.d(TAG, "onAuthStateChanged:signed_in:" + user.getUid());
} else {
// User is signed out
Log.d(TAG, "onAuthStateChanged:signed_out");
}
// ...
}
};

Categories

Resources