1

I have firebase database rules set up like this

"Users":{
        
         "$user_id":{

            "Name":{
                    ".read":"auth != null",
                    ".write":"auth.uid == $user_id"
                },

            "Email":{
                    ".read":"auth != null",
                    ".write":"auth.uid == $user_id"
                },

            "Address":{
                    ".read":"auth != null",
                    ".write":"auth.uid == $user_id"
                },

            "Photo":{
                    ".read":"auth != null",
                    ".write":"auth.uid == $user_id"
                },

            "Number":{
                    ".read":"auth.uid == $user_id",
                    ".write":"auth.uid == $user_id"
                }
,
            "Current":{
                    ".read":"auth != null",
                    ".write":"auth.uid == $user_id"
            }
         }

       }

The code that makes the request

FirebaseAuth mAuth = FirebaseAuth.getInstance();
DatabaseReference userRef = FirebaseDatabase.getInstance().getReference().child(FirebaseConstants.USERS).child(mAuth.getCurrentUser().getUid());

if(mAuth.getCurrentUser() !=null)
{
    Log.i("DetailsActivity","User id "+mAuth.getCurrentUser().getUid());

}
else
{
    Log.i("DetailsActivity","User not authenticated");
}
                       
userRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
    public void onDataChange(@NonNull DataSnapshot dataSnapshot) {

                if(dataSnapshot.hasChild(FirebaseConstants.NAME))
                {
                    Name = dataSnapshot.child(FirebaseConstants.NAME).getValue().toString();
                    UserNameEdittext.append(Name);

                }
                if(dataSnapshot.hasChild(FirebaseConstants.EMAIL))
                {
                    Email = dataSnapshot.child(FirebaseConstants.EMAIL).getValue().toString();
                    UserEmailEdittext.append(Email);
                }
                userInfoProgressbar.setVisibility(View.INVISIBLE);

            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

                userInfoProgressbar.setVisibility(View.INVISIBLE);
                Log.i("DetailsActivity","error "+databaseError);

            }
            
});                    
  

Logged Results

I/DetailsActivity: User id KfiIFOEGWQZIc5UREqX8qo4Nmkn1
I/DetailsActivity: error DatabaseError: Permission denied

When an authenticated user is making a request to the $user_id node under users node, it results in Permission Denied error. Firebase database rules works atomically, but all the read permissions are checking whether he is an authenticated user or the user is accessing his own data. When the user reads his own data and all read conditions are satisfied but still getting Permission Denied error.

But when I try to read any of these fields individually there is no errors

userRef.child(FirebaseConstants.NAME).addListenerForSingleValueEvent(new ValueEventListener() {
@Override
    public void onDataChange(@NonNull DataSnapshot dataSnapshot) {

                if(dataSnapshot.exists())
                {
                    Name = dataSnapshot.getValue().toString();
                    Log.i("DetailsActivity","Name "+Name);

                }

            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

                userInfoProgressbar.setVisibility(View.INVISIBLE);
                Log.i("DetailsActivity","error "+databaseError);

            }        
});

I get the log as

I/DetailsActivity: Name elsonjose

Any help is appreciated. Thanks in advance.

Elson Jose
  • 27
  • 4
  • Please edit the question to show the code that performs the query. Also illustrate in that example that you are certain that a user is signed in at the time of the query. – Doug Stevenson Aug 05 '20 at 16:11
  • try with these: https://stackoverflow.com/questions/40942493/android-firebase-database-error-permission-denied/50450701#:~:text=Go%20to%20firebase%20console%20and,write%20operations%20on%20your%20database.&text=Go%20to%20the%20Rules%20tab,then%20permission%20will%20be%20denied. https://stackoverflow.com/questions/37424544/firebase-database-permission-denied-with-read-write-permissions-set-to-true – Sadegh J Aug 05 '20 at 16:41
  • @Sadegh Tried refreshing google-services.json, no luck there. – Elson Jose Aug 05 '20 at 16:56

1 Answers1

1

Assuming that you have a default set to:

  "rules": {
    ".read": false,
    ".write": false,

You do have rules for single fields, but you are likely getting "Permission denied" when reading the whole user record because you don't have any rules set for the "$user_id" path itself. Try adding:

    "Users": {
          "$user_id": {
            // Allow only authenticated content owners access to their data
            ".read": "auth != null && auth.uid == $user_id",
            ".write": "auth != null && auth.uid == $user_id"
          } 
...
Dmitri Borohhov
  • 1,513
  • 2
  • 17
  • 33
  • Yes this works, but I wanted to allow certain users to access only particular data. After going through the documentation I found out that we cant really use firebase rules for filtering users. For filtering users some of the links that I found useful are [https://www.toptal.com/firebase/role-based-firebase-authentication] [https://medium.com/firebase-tips-tricks/how-to-create-an-admin-module-for-managing-users-access-and-roles-34a94cf31a6e#:~:text=Most%20applications%20need%20to%20implement,to%20implement%20such%20a%20system.] – Elson Jose Aug 06 '20 at 03:55
  • If you want to have user roles and rules around them, you can create a "profiles" collection in the database where you store user properties. That's the only way I know to achieve the functionality purely with firebase tools. – Dmitri Borohhov Aug 06 '20 at 07:15