Does anyone know why I can't use this snippet from here https://firebase.google.com/docs/rules/basics#realtime-database_2
It looks like a documentation mistake because in Firestore you would write request.auth.uid while in the RTDB you just write auth.uid.
{
"rules": {
"some_path": {
"$uid": {
// Allow only authenticated content owners access to their data
".read": "auth != null && auth.uid == $uid",
".write": "auth != null && auth.uid == $uid"
}
}
}
}
Related
I'm trying to create a rule for create/access the FRD data based on authenticated user. But am getting an error where running the Rules Playground
What I want is, Users are creating the categories. So Users is able to only read their categories and update those categories.
Rule:
{
"rules": {
"users": {
"$uid": {
".write": "auth != null && $uid === auth.uid",
".read": "auth != null && $uid === auth.uid"
}
},
"categories": {
"$uid": {
".write": "auth != null && $uid === auth.uid",
".read": "auth != null && $uid === auth.uid"
}
}
}
}
Auth Users:
Realtime Database
Categories
Users
Categories Write function in Flutter
String uId = await userId();
final databaseRef = FirebaseDatabase.instance.ref('categories');
var data = await databaseRef.get();
var index = data.children.length;
await databaseRef.child('$index').set(<String, dynamic>{
"name": categoryBody.name,
"description": categoryBody.description,
"uid": uId,
"id": index,
});
Error
Is there anything wrong with the rules that am applying?
I tried to replicate your issue, but I can able to successfully test rules without errors.
The rules you are using are for authenticated users but you are testing for unauthenticated users. Means you have not enabled Authenticated field.
And you have to enter /categories/uid instead of /categories under the location and you should enter uid under Firebase UID field. You may have look at below screenshot.
You can refer this tutorial for more information.
When you're using the following security rules:
"categories": {
"$uid": {
".write": "auth != null && $uid === auth.uid",
".read": "auth != null && $uid === auth.uid"
}
}
It means that you allow the user to write/read to/from every child that exists under your categories/$uid node. So when you try to apply those rules to your actual database structure, it's the expected behavior to see that Firebase servers reject the operations since it doesn't find any $uid level in your database schema. To solve this, you have to remove that extra $uid level from rules like this:
"categories": {
".write": "auth != null",
".read": "auth != null"
}
And this is because those category objects exist directly under the categories node and not under categories/$uid.
I need to allow only 2 specific uid for write access and I can't publish with my current rule:
{
"rules": {
".read": "auth != null",
".write": "auth != null && auth.uid === 'abc123' || '123abc'",
}
}
It keeps complain "rule regulation may not contain '|' operator" and
"right operand for '||' must be boolean", which ever i used.
How should I change my rule to achieve what I want?
Any help will be much appreciated.
The word after || is actually not a boolean, it is just a string. Please, check my fixed code.
{
"rules": {
".read": "auth != null",
".write": "auth != null && (auth.uid === 'abc123' || auth.uid === '123abc')",
}
}
I try to allow write for a list of uid using, auth.uid in ['ciAujxIqXQSdaaaaaaaaaa', 'bbb'], but that's not the correct syntax, how can I do this?
{
"rules": {
"orders": {
".read": "auth != null",
".write": "(data.child('uid').val() == auth.uid) || auth.uid in ['ciAujxIqXQSdaaaaaaaaaa', 'bbb']",
".indexOn": ["negative_epoch"]
},
"users": {
".read": "auth != null",
".write": "auth != null",
},
}
}
There is no in operation in the security rules language for the Realtime Database. So you'll have to do an or yourself:
"(data.child('uid').val() == auth.uid) || auth.uid == 'ciAujxIqXQSdaaaaaaaaaa' || auth.uid == 'bbb'"
I usually find that after adding 2 or 3 UIDs this way, I create a new top-level list in the database to hold these UID:
"admins": {
"ciAujxIqXQSdaaaaaaaaaa": true,
"bbb": true
}
And then check against that list in my rules:
"(data.child('uid').val() == auth.uid) || root.child('admins').child(auth.uid).exists()"
Im having trouble with the security rules for firebase and Im not 100% where I am going wrong. I am thinking that maybe I have my data structure wrong:
{
"users": {
"uid": {
"displayName": "Name";
}
},
"modules": {
"id": {
"title": "buttons",
"uid": "(user id string)"
},
"id": {
"title": "navbars",
"uid": "(user id string)"
}
},
"snippets": {
"id = moduleID": {
"id (of snippet)": "(id string)" {
"uid (user ID)": "(string)",
"body": {
"css": "(some code)",
"html": "(Some code)",
"name": "(string)",
"description": "(string)"
}
}
}
}
Everything in the app works fine, but when I started to add security rules I got access denied errors. Im just wondering if I have the data structure correct in the first place or is the security rules completely wrong?
Security rules:
{
"rules": {
"users": {
"$uid": {
// grants write and read access to the owner of this user account whose uid must exactly match the key ($uid)
".write": "auth != null && auth.uid == $uid",
".read": "auth != null && auth.uid == $uid"
}
},
"snippets": {
"$uid": {
// grants write and read access to the owner of this user account whose uid must exactly match the key ($uid)
".write": "auth != null && auth.uid == $uid",
".read": "auth != null && auth.uid == $uid"
}
},
"modules": {
"$uid": {
// grants write and read access to the owner of this user account whose uid must exactly match the key ($uid)
".write": "auth != null && auth.uid == $uid",
".read": "auth != null && auth.uid == $uid"
}
}
}
Any advice would be greatly appreciated.
It seems the rules are malformed based on the data structure.
The rules have $uid's in each node but your data doesn't match that. Users has uid but modules has id and snippets has id = moduleID.
$uid is a variable that holds the node name so it can be referenced inside { } so you should (for readability) rename that variable in the other two nodes to something that makes more sense inside each {}. Like in modules, have it $module_id.
However. I think the jest of this is you want to limit reading snippets and modules to authenticated users. To do that, you can reference the users node.
a .read rule would be something like this
"modules": {
"$module_id": {
".read": "auth != null && root.child('users/' + auth.id).exists()
}
So your modules node can be read by a user that is auth'd and their uid also appears in the users/ node
Are you using the Firebase Bolt compiler for rules? I had to write some complex rules and doing it by hand gets confusing very quickly.
Below is what it would looks like. Very easy to make changes, compile and try them out.
//current logged in user
isUser(uid) = auth != null && auth.uid == uid;
//does this module id exist
hasValidModule(module_id) = root['modules'][module_id] != null;
//dont let anyone read or write to top node
path / {
read() = false;
write() = false;
}
path /users/$user_id
{
write() = isUser($user_id);
read() = isUser($user_id);
}
path /snippets/$module_id/$snipit_id/$user_id
{
write() = isUser($user_id) && hasValidModule($module_id);
read() = isUser($user_id);
}
path /modules/$user_id
{
write() = isUser($user_id);
read() = isUser($user_id);
}
Here's the json it spits out:
{
"rules": {
"users": {
"$user_id": {
".read": "auth != null && auth.uid == $user_id",
".write": "auth != null && auth.uid == $user_id"
}
},
"snippets": {
"$module_id": {
"$snipit_id": {
"$user_id": {
".read": "auth != null && auth.uid == $user_id",
".write": "auth != null && auth.uid == $user_id && newData.parent().parent().parent().parent().child('modules').child($module_id).val() != null"
}
}
}
},
"modules": {
"$user_id": {
".read": "auth != null && auth.uid == $user_id",
".write": "auth != null && auth.uid == $user_id"
}
}
}
}
There's some info on the Firebase blog but the doc that really helped me is this
https://github.com/firebase/bolt/blob/master/docs/language.md
So I have this db structure:
Under profile I want email & provider-name to be readable only for admin and
Username readable for every logged in user.
How I can achieve that?
Here is my rules:
{
"rules":
{
"users":
{
"$uid":
{
// grants write access to the owner of this user account whose uid must exactly match the key ($uid)
".write": "auth !== null && auth.uid === $uid",
"profile":
{
// grants read access only for registered users
".read": "auth !== null",
"email":
{
// This doesn't work with firebase as I was reading doc.
".read": false
}
}
}
}
}
}
So after a bit of research and reading about denormalize structure I guess this way will work. The fact is that I'm tempted to nest, but probably is a bad idea on firebase.
{
"rules":
{
"users":
{
"$uid":
{
// grants write access to the owner of this user account whose uid must exactly match the key ($uid)
".write": "auth !== null && auth.uid == $uid",
"public-profile":
{
// grants read access only for registered users
".read": "auth !== null"
}
}
},
"private-profile":
{
"$uid":
{
".read": "root.child('users').child(auth.uid).child('role').child('admin').val() === 'true' && root.child('users').child('1').child('role').child('admin').val() === 'true'",
".write": "root.child('users').child(auth.uid).child('role').child('admin').val() === 'true' && root.child('users').child('1').child('role').child('admin').val() === 'true'"
}
}
}
}