Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Firebase Permission denied when reading data after authentication

I am new to Firebase. I authenticated the user using email and password -

final Firebase ref = new Firebase("https://app.firebaseio.com");
ref.authWithPassword("[email protected]", "password", new Firebase.AuthResultHandler() {

    @Override
    public void onAuthenticated(AuthData authData) {
        System.out.println("User ID: " + authData.getUid());
        getData(ref);
    }

    @Override
    public void onAuthenticationError(FirebaseError firebaseError) {
    }
});

But after authentication when I am reading the data, I am getting Permission Denied.

private void getData(Query ref) {
    ref.addValueEventListener(new ValueEventListener() {

        @Override
        public void onDataChange(DataSnapshot snapshot) {
            System.out.println(snapshot.getValue());
        }

        @Override
        public void onCancelled(FirebaseError firebaseError) {
            System.out.println("The read failed: " + firebaseError.getMessage());
        }
    });
}

These are the Firebase rules.

{
    "rules": {
        "users": {
            "$uid": {
                ".read": "auth !== null && auth.provider === 'password'"
            }
        }
    }
}
like image 343
mihirjoshi Avatar asked Dec 11 '22 20:12

mihirjoshi


2 Answers

Firebase's permission model only allows the user access to data that you explicitly give access to. Since in your security rules, you only give access to /users/$uid, the user cannot read from root /. The Firebase documentation covers this under "rules cascade".

You seem to want to use security rules to filter data, which is not possible with Firebase's security model. See the section "rules are not filters" in the Firebase documentation as well as these previous questions and answers:

  • firebase security permission not working
  • firebase rules not working
  • How to use Firebase rules to only give permission to certain leaf nodes

The simplest solution is to allow read of the users node:

{
    "rules": {
        "users": {
            ".read": "auth !== null && auth.provider === 'password'"
        }
    }
}

And then query on that level:

getData(ref.child("users"));
like image 143
Frank van Puffelen Avatar answered Jan 18 '23 22:01

Frank van Puffelen


I got this exception using a slightly different approach to read from my database, but this is how I solved the issue.

First of all, my database rules looked liked this:

{
"rules": {
  "student": {
    "$uid": {
      ".write": "auth != null && auth.uid == $uid",
      ".read": "auth != null && auth.uid == $uid"
      }
    }
  }
}

Earlier on, to write to to the student database, I used this code in my Activity:

 mAuthListener = new FirebaseAuth.AuthStateListener() {
        @Override
        public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
            user = firebaseAuth.getCurrentUser();
            if (user != null) {
                // User is signed in
                Log.e(TAG, "onAuthStateChanged:signed_in:" + user.getUid());
            } else {
                // User is signed out
                Log.e(TAG, "onAuthStateChanged:signed_out");
            }
            // ...
        }
    };
    ...
    Student student = new Student();
    student.setPhoneNumber("+23480547455343");
    student.setCountryOfOrigin("Nigeria");
    mDatabaseReference.child("student").child(user.getUid()).setValue(student).
                addOnCompleteListener(DetailsCaptureActivity.this, 
                                   new OnCompleteListener<Void>() {
     ...
     });

Notice how the child name (student) matches the child name in the firebase data rules?

Now to read the data of this user, I did this:

 //Set up an AuthStateListener that responds to changes in the user's sign-in state:
    mAuthListener = new FirebaseAuth.AuthStateListener() {
        @Override
        public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
            user = firebaseAuth.getCurrentUser();
            if (user != null) {

                   databaseReference = firebaseDatabase.getReference().child("student").child(user.getUid());
                   databaseReference.addValueEventListener(new ValueEventListener() {
                      @Override
                      public void onDataChange(DataSnapshot dataSnapshot) {
                          Student student = dataSnapshot.getValue(Student.class);
                          phoneNumberTextView.setText(student.getPhoneNumber());
                      }

                      @Override
                      public void onCancelled(DatabaseError databaseError) {

                          Log.e(TAG, databaseError.getMessage());
                      }
                  });

            } else {
                Log.e(TAG, "onAuthStateChanged:signed_out");
            }
        }
    };

I got the permission denied exception if I did only:

databaseReference = firebaseDatabase.getReference().child(user.getUid());
like image 40
Ojonugwa Jude Ochalifu Avatar answered Jan 18 '23 22:01

Ojonugwa Jude Ochalifu