Search code examples
javascriptfirebasefirebase-realtime-databasefirebase-securityangularfire2

Firebase RealTime database rules to restrict on user id runs in simulator but not in AngularFire


If you look at the screenshot you can see that the simulated test passes:

firebase test

It restricts adding user data to the users node if the uid does not match.

You can see the location is:

/users/6OCBYNh3CTammMWrCjX0F003zab2

In other words:

/users/$uid

When I try to do this from code, I get a permission denied error:

  private async addNewUserToFirebase(user: firebase.User): Promise<void> {
    console.log('adding user to Firebase', user);

    try {
      const ref = this.db.list('/users');
      await ref.update(user.uid, {email: 'test@test.com'});    
    } catch (error) {
      console.error('Unable to add user to firebase db', error);
    }
  }

@firebase/database: FIREBASE WARNING: update at /users/6OCBYNh3CTammMWrCjX0F003zab2 failed: permission_denied

However, if I change the rule to simply

".write": "auth != null" 

then it works. So why is it failing when I try to match the uid?

NOTE

I have also tried:

     const refAccount = this.db.list('/users');      
     await refAccount.update(`/${user.uid}`, {email: "test@test.com");

and get the same error.

I have tried with multiple users from both the simulator and code. The results are consistent.

Yet this question shows identical rules, and for that OP it works.


Solution

  • So this seems to be an issue with getRedirectResults()

    Further testing has uncovered that this code works (with the rule userId === auth.id):

    this.angularFireAuth.onAuthStateChanged(user => {
      firebase
        .database()
        .ref('users')
        .child(user.uid)
        .child('email')
        .set('test@test.com');
    });
    

    but this does not, as the user is always null:

      this.angularFireAuth.getRedirectResult().then(credential => {
        firebase
          .database()
          .ref('users')
          .child(credential.user.uid)
          .child('email')
          .set('test@test.com');
      });
    

    This still does not explain why sometimes auth.uid !== null works.

    But it seems I am not the only person with a null user on getRedirectResults() as you can see here and there is an official bug report here