Reputation: 3180
I'm new to Firebase, and I'm trying to understand rules where authenticated user id is to be used for securing data. I'm using Angularfire2 on the client. And I'm using email/password authentication, which works fine.
If I set my database rules to allow read and write for authenticated users, everything works fine, and I end up with the following data in the Firebase database...
{
"notes" : {
"-KmgjG9hxoXOTtuLTItz" : {
"content" : "test",
"title" : "Test note 1",
"uid" : "iLH4Kg20shViwJebCmU8Ynp0OG23"
},
{
"-Kmh5igvItrJstbAhRpq" : {
"content" : "test",
"title" : "Test note2",
"uid" : "iLH4Kg20shViwJebCmU8Ynp0OG23"
}
}
}
Now I want to restrict read and write permissions where the authenticated user matches the user id (uid) set on each object, so I changed the rules as follow...
{
"rules": {
"notes": {
".read": "data.child('uid').val() == auth.uid",
".write": "newData.child('uid').val() == auth.uid"
}
}
}
However, this does not work. Reads fail with...
ERROR Error: permission_denied at /notes: Client doesn't have permission to access the desired data.
...and writes fail with...
FIREBASE WARNING: set at /notes/-KmgjG9hxoXOTtuLTIpG failed: permission_denied
I know that the user is authenticated because if I hard-code the user id in the rules like below, it works just fine...
{
"rules": {
"notes": {
".read": "auth.uid == 'iLH4Kg20shViwJebCmU8Ynp0OG23'",
".write": "auth.uid == 'iLH4Kg20shViwJebCmU8Ynp0OG23'"
}
}
}
Upvotes: 1
Views: 1155
Reputation: 3180
I was able to solve this by restructuring my data schema, putting the user id in the path, not in the object, e.g., /users/<-uid->/notes/, and using the following rules...
{
"rules": {
"users": {
"$userId": {
".read": "$userId === auth.uid",
".write": "$userId === auth.uid"
}
}
}
}
As per the comments regarding "rules are not filters", I get that now. The thing that was tripping me up was where the Firebase database rules doc was referring to "children" with key-value pairs, e.g.,...
This example only allows reading if the isReadable child is set to true at the location being read.
".read": "data.child('isReadable').val() == true"
To me that implied that the JSON data structure is something like this...
{ ..., isReadable: true, ...}
But I guess that is referring to location paths, e.g., /users/fred/isReadble or something like that. Not quite sure. It seems odd. But regardless, I got it working.
Upvotes: 2
Reputation: 684
I think you are forgetting the key:
{
"rules": {
"notes": {
"$key": {
".read": "auth.uid == 'iLH4Kg20shViwJebCmU8Ynp0OG23'",
".write": "auth.uid == 'iLH4Kg20shViwJebCmU8Ynp0OG23'"
}
}
}
}
I might be missing something else but you are targeting a list with autogenerated keys (accessible in your rules with a "$somevar").
Upvotes: 0