My Firebase realtime database security rules: validate not working - firebase

{
"rules": {
"interviews": {
".read": true,
".write": "auth != null && root.child('admins').child(auth.uid).exists()",
"thumbnail" :{
".validate" : "newData.val() != 0 || (newData.val() == 0 && data.val() == 'uploading')"
},
"soundbyte" :{
".validate" : "newData.val() != 0 || (newData.val() == 0 && data.val() == 'uploading')"
}
},
"token": {
".read": false,
".write": "auth != null && auth.isAdmin == true"
},
"admins":{
".read" : false,
".write": "auth != null && auth.isAdmin == true"
}
}
}
Can you tell any problem with my security rules, as I am trying to add a validation to my thumbnail's data.
Here is a little data structure example I am gonna use with it.
interviews
-K_l_pkOTUYovqRwajln
detail: "YO"
soundbyte: "interview_sb_KlpkOTUYovqRwajln.mp3"
thumbnail: "uploading"
title: "Episode Five"
video_url: ""
-K_ll31srQ46vgtDXX1n
detail: "Duncan lives in a town."
soundbyte: "interview_sb_KllsrQvgtDXXn.mp3"
thumbnail: "interview_thumb_KllsrQvgtDXXn.jpg"
title: "Duncan"
video_url: ""

Related

Firebase realtime database leaks protected data in websocket connection?

I have defined a realtime database rule as follows:
{
"rules": {
".read": false,
".write": false,
"devices": {
".read": "auth.uid != null && query.orderByChild == 'ownerUid' && query.equalTo == auth.uid",
"$device": {
".read": "data.child('ownerUid').val() == auth.uid",
"nickname": {
".write": "data.parent().child('ownerUid').val() == auth.uid",
".validate": "newData.isString() && newData.val().length < 30"
},
"ownerUid": {
".validate": "root.hasChild('users/' + newData.val())"
},
... additional fields here
}
}
}
}
In my web application, using reactfire and firebase npm modules, I have queried for a device as follows:
const devicesRef = useDatabase()
.ref(`devices`)
.orderByChild('ownerUid')
.equalTo(user.uid);
const { data: devices, status } = useDatabaseListData<Device>(devicesRef, { idField: 'id' });
This appears to work, but if I look in the network tab, I can see all of the data come back, not just the data that is supposed to come back. The data returned to my code is the data that I would expect.
Note in the screenshot below that all data comes back, even data that does not have ownerUid defined.
I am using the example from the documentation almost exactly: https://firebase.google.com/docs/database/security/rules-conditions#query-based_rules
Am I doing something wrong? or is this a bug in Firebase?
I discovered the solution after upgrading my firebase client version and getting some new errors from it. It turns out the issue was that I was missing an index on ownerUid.
The new rules look like this:
{
"rules": {
".read": false,
".write": false,
"devices": {
".indexOn": ["ownerUid"],
".read": "auth.uid != null && query.orderByChild == 'ownerUid' && query.equalTo == auth.uid",
"$device": {
".read": "data.child('ownerUid').val() == auth.uid",
"nickname": {
".write": "data.parent().child('ownerUid').val() == auth.uid",
".validate": "newData.isString() && newData.val().length < 30"
},
"ownerUid": {
".validate": "root.hasChild('users/' + newData.val())"
},
... additional fields here
}
}
}
}

How safe it is this rule?

Firebase database question:
I want to "open" "votes" for unauthenticated users. Is this safe ?
Maybe:
{
"rules": {
".read": true,
"posts": {
"title": { ".write": "auth != null && auth.uid == 'XXXXXX'"},
"url": { ".write": "auth != null && auth.uid == 'XXXXXX'"},
"time": { ".write": "auth != null && auth.uid == 'XXXXXX'"},
"vote": {".write": true,}
}
}
}
Or:
{
"rules": {`enter code here`
".read": true,
"posts": {
"title": { ".write": "auth != null && auth.uid == 'XXXXXX'"},
"url": { ".write": "auth != null && auth.uid == 'XXXXXX'"},
"time": { ".write": "auth != null && auth.uid == 'XXXXXX'"},
"vote": {".write": "newData.val() === data.val() + 1"}
}
}
}

What is the best way of implementing firebase rules? Mine's not working [duplicate]

This question already has an answer here:
How to implement a role based access control with AngularFire
(1 answer)
Closed 4 years ago.
This is my firebase rules
{
"rules": {
".read": "auth != null",
".write": "root.child('users/auth.id/user_type').val() == 'admin'"
}
}
My users node. (Data is faked)
{
"users" : {
"2anxMpsdsxsd5K2" : {
"user_email" : "dsds#gmail.com",
"user_name" : "dsd",
"user_photo_url" : "somepic.jpg",
"user_roles" : {
"writer" : true
}
},
"z8uzffddelsSl1" : {
"user_email" : "xcxc#gmail.com",
"user_name" : "xcxc",
"user_photo_url" : "fb-picture",
"user_type" : "admin"
}
}
}
I tried with user roles but was still denied from writing. Would my rules be the one that's faulty?
This is what I came up with.
{
"rules": {
"users": {
".read": "auth != null",
"$user_id": {
".write": "auth.uid == $user_id || root.child('users').child(auth.uid).child('user_type').val() == 'admin'"
}
},
// "news": {
// "$news_id": {
// ".read": "auth != null",
// ".write": "auth.uid == root.child('news').child($news_id).child('news_author_id').val() || root.child('users').child(auth.uid).child('user_type').val() == 'news_contributor' || root.child('users').child(auth.uid).child('user_type').val() == 'admin' "
// }
// },
"programs": {
".read": "auth != null",
"courses": {
"$course_id": {
".write": "auth.uid == root.child('programs').child('courses').child($course_id).child('program_author_id').val() || root.child('users').child(auth.uid).child('user_type').val() == 'admin'"
}
},
"tracks": {
".read": "auth != null",
"$track_id": {
".write": "auth.uid == root.child('programs').child('tracks').child($track_id).child('program_author_id').val() || root.child('users').child(auth.uid).child('user_type').val() == 'program_contributor' || root.child('users').child(auth.uid).child('user_type').val() == 'admin'"
}
}
},
"news": {
".read": "auth != null",
"$news_id": {
".write": "root.child('users').child(auth.uid).child('user_type').val() == 'news_contributor' || auth.uid == root.child('news').child($news_id).child('news_author_id').val() == auth.uid || root.child('users').child(auth.uid).child('user_type').val() == 'admin'"
}
}
}
}
One problem though.
this error pops up
error TS7027: Unreachable code detected.

Unable to validate child nodes with Firebase security

I'm clearly missing some fundamental aspect of firebase security, because this shouldn't work. I would expect it to throw a validation error when attempting to push invalid data. (Inserting a new node into /nodes)
Rules:
{
"rules": {
"nodes": {
".read": "auth !== null && auth.provider === 'google'",
".write": "auth !== null && auth.provider === 'google'",
"user": {
".validate": "newData.val() === auth.uid"
},
"ts": {
".validate": "newData.val() <= now && newData.val() >= (now-1000*60*60*24)"
}
}
}
}
Then in my console I try to intentionally insert invalid data:
ref.child('nodes').push({
'user': 'abc',
'ts': 123
}, function(err){console.log(err);});
Which logs null, and when I check my database it was inserted, no validation errors! I know I've got something fundamentally wrong, because a validation rule right after the .read and .write rows of the following disallows any writing. .validate": "newData.hasChildren(['user', 'ts'])",
{
"nodes" : {
"-KAgH0BLneWfGu8NymBo" : {
"ts" : 123,
"user" : "abc"
}
}
}
Whoops. Missing "$node_id"
{
"rules": {
"nodes": {
"$node_id":{
".read": "auth !== null && auth.provider === 'google'",
".write": "auth !== null && auth.provider === 'google'",
"user": {
".validate": "newData.val() === auth.uid"
},
"ts": {
".validate": "newData.val() <= now && newData.val() >= (now-1000*60*60*24)"
}
}
}
}
}

How to allow specific user access to firebase nodes?

I want to allow all logged in user access to create new content, but only those who are owners should be able to update the data. I can't figure out how to do this, this is what I have tried:
{
"rules": {
".read": false,
".write": false,
"videos": {
".read": true,
".indexOn": ["id", "title_lower_case"],
"$video": {
".write": "(auth !== null && auth.provider === 'password' && (!newData.exists() || newData.hasChildren())) || (auth.uid === root.child('videos').child($video).child('uid').val())",
".validate": "newData.hasChildren(['id', 'title', 'title_lower_case', 'uid'])",
"id": {
".validate": "newData.isString() && newData.val().length >= 5 && newData.val().length <= 1000"
},
"title": {
".validate": "newData.isString() && newData.val().length >= 2 && newData.val().length <= 1000"
},
"title_lower_case": {
".validate": "newData.isString() && newData.val().length >= 2 && newData.val().length <= 1000"
},
"uid": {
".validate": "newData.val() === auth.uid"
},
"$other": {
".validate": false
}
}
},
"users": {
".read": true,
"$user": {
".read": "auth !== null && auth.provider === 'password'",
".write": "auth.uid === $user && (!newData.exists() || newData.hasChildren())",
".indexOn": "name_lower_case",
".validate": "newData.hasChildren(['email', 'name', 'name_lower_case'])",
"email": {
".validate": "newData.isString() && newData.val().length <= 2000"
},
"name": {
".validate": "newData.isString() && newData.val().length >= 2 && newData.val().length <= 2000"
},
"name_lower_case": {
".validate": "newData.isString() && newData.val().length >= 2 && newData.val().length <= 2000"
},
"$other": {
".validate": false
}
}
}
}
}
I thought that this part allowed any logged in user to create a new node:
auth !== null && auth.provider === 'password' && (!newData.exists() || newData.hasChildren())
And this part only allowed owners to edit the node:
auth.uid === root.child('videos').child($video).child('uid').val()
Btw, I use the simple login feature in firebase if that has anything to say.
Doing the below seemed to do the trick. If the auth variable exists, then allow write abilities. Due to me not fully understanding these rules, I have to wonder if this is running against the current user or if it's checking to see if any user is logged in.
{
"rules": {
"product":{
".read": true,
".write":"auth !== null"
}
}
}

Resources