pythondatabasefirebasefirebase-realtime-databasepyrebase

Firebase realtime database permission error even though rules playground simulation succeeds


My database has a users child with fields email and name, with the key being the users uid. Here are the database rules:

{
  "rules": {
     "users": {
       "$uid": { 
         "email": {
           ".read": "auth.uid == $uid",
           ".write": "auth.uid == $uid"
        },
         "name": {
           ".read": "auth.uid == $uid",
           ".write": "auth.uid == $uid"
        }
      }
    }
  }
}

I am using pyrebase to access the firebase project. Here is the statement that tries to add them to users:

db.child("users").child(self.user["localId"]).set({"name": name, "email" : email})

While creating a new user, I get a permission denied error. The user is still able to sign in though. When I make a simulated request with the rules playground, it succeeds.

edit: Here is a reproducible example:

import pyrebase

config = {
    "apiKey": "",
    "authDomain": "",
    "projectId": "",
    "databaseURL": "",
    "storageBucket": "",
    "messagingSenderId": "",
    "appId": "",
    "measurementId": "",
}
firebase = pyrebase.initialize_app(config)
user = firebase.auth().sign_in_with_email_and_password("test@gmail.com", "password")
db = firebase.database()
db.child("users").child(user["localId"]).set({"name": "test", "email": "test@gmail.com"}, token=user["localId"])

Solution

  • The user ID (user["localId"]) shouldn't be passed in as the authentication token. You need to pass the user's ID token instead (user["idToken"]). So while you may be writing to the correct location, you are doing so without providing the right authorization.

    db.child("users").child(user["localId"]).set({"name": "test", "email": "test@gmail.com"}, user["idToken"])