firebase with auth and without auth security rules - firebase

I want to create a firebase rule where people can use the database without having to login. But I also want to make a private user node where only the user can acces it by authenticating so far I have something like this. But this trows an error
Error saving rules - Line 6: Expected '}'.
{
"rules": {
".read": true,
".write": "newData.exists()"
},
"test": {
"$uid": {
".read": "auth != null && auth.uid == $uid",
".write": "auth != null && auth.uid == $uid"
}
}
}
I do not understand why the above is not possible
But if I do only:
{
"rules": {
".read": true,
".write": "newData.exists()"
}
}
This wil work so that anyone can use the current data but I want to have something private like "Test" where the people who authenticated themself only have access to
So to be clear I want everyone to use the current database but I also want to have some private parts like test only accesable for registered users

Have a look at https://firebase.google.com/docs/database/security/securing-data
You cannot add an element after "rules". It should be like:
{
"rules": {
...
}
}
and not like
{
"rules": {
....
},
....
}

Related

Firebase hierarchy security rules

I have a problem restricting access to the children of the object
The rules I need:
roles - read
-- UID
--- SUPUSR
---- settings = read only
--- store = write and read
My rules
"roles":{
".read":"auth != null",
".write":"root.child('roles/SUPUSR/').child(auth.uid).child('settings').child('pri_enabled').val() == 1 || root.child('roles/USERS/').child(auth.uid).child('settings').child('pri_enabled').val() == 1",
"settings":{
".read":"auth != null",
".write":false
}
If I leave it the way it is above, it inherits the "roles" rules for writing
Firebase Realtime Database Rules cascade, once you grant permission, you cannot revoke it. So if you allow write access on /roles, anyone can write to any child of /roles whether it's their own or someone else's data.
Other notes:
The current rules affect /roles and /roles/settings, which is too high in the database tree, you should be setting the rules of /roles/SUPUSR/someUserId, /roles/SUPUSR/someUserId/settings and so on.
The use of auth != null seems out of place. Should any logged in user be able to read any other user's roles? Should this only work for super users?
Some of the data would also make sense to be validated.
{
"rules": {
"roles": {
"SUPUSR": {
"$uid": {
// any data under /roles/SUPUSR/$uid is readable to logged in users
".read": "auth != null",
"nome": {
// only this user can update nome, it also must be a string
".write": "auth.uid === $uid",
".validate": "newData.isString()"
},
"role": {
// only this user can update role, and it must be one of a select number of string values
".write": "auth.uid === $uid",
".validate": "newData.isString() && newData.val().matches(/^(R&S|Admin|etc)$/)"
},
"store": {
".write": "root.child('roles/SUPUSR/').child(auth.uid).child('settings').child('pri_enabled').val() == 1 || root.child('roles/USERS/').child(auth.uid).child('settings').child('pri_enabled').val() == 1"
}
// any other keys are ".write": false, by default, which includes "settings"
}
}, // end /rules/roles/SUPUSR
"USERS": {
"$uid": {
...
}
}, // end /rules/roles/USERS
...
}, // end /rules/roles
...
}
}

How can I give write permission to a specified user in Firebase?

I have a mobile application which reads the data from the firebase server without firebase login/authentication (posts and news) and I want to create an admin webpage where I can log in and add, or modify news, so I need a write permission there. My rules are currently:
{
"rules": {
".read": true,
".write": "auth !== null && ?????
}
}
Can I write something like "user.emailAddress == 'mail#example.com'"?
You can create a users table on database like
{
"users":{
"your UID":{
"isAdmin": true
}
}
}
Then edit rules :
{
"rules": {
".read": true,
".write": "auth.uid != null && root.child("users").child(auth.uid).isAdmin === true"
}
}
You might want to start by reading the documentation about securing user data. There is a lot to know here.
One possibility is using the known user's uid to restrict access. The auth.uid variable contains the uid.
".write": "auth.uid == 'the-known-uid'"
Also you can use auth.token to access some other things about the user, including email address (which may not be present):
".write": "auth.token.email == 'the#email.address'"
You can also use custom authentication tokens, which also is covered in the documentation.
Create database:
{
"users":{
"your UID":{
"isAdmin": true
}
}
}
Set rules:
Wrong:
{
"rules": {
".read": true,
".write": "auth.uid != null && root.child("users").child(auth.uid).isAdmin === true"
}
}
Right:
{
"rules": {
".read": true,
".write": "auth.uid != null && root.child('users').child(auth.uid).child('isAdmin').val() === true"
}
}

Read only children of a list that have a field with the value of auth.uid

This is my DB structure
"tasks"
"$taskId"
...
"user": "firebase user id"
I have already written a rule ".read": data.child('user').val() === auth.uid" under $taskId. When I try to access a single task, this rule is taking effect.
Will this also guarantee that if I write a query like firebase.database().ref('/tasks').orderByChild('status').limitToFirst(1) I'll only get tasks that have user id field as auth.uid. Or should I also write a .read clause under tasks
There are several aspects to be answered in your question:
1/ At which level should you write the security rules?
If you write only at the task level like just follows, you will not be able to query the entire set of tasks.
You can test it by doing the following:
Rules:
{
"rules": {
"tasks": {
"$taskID": {
".read": "auth != null",
".write": "auth != null"
}
}
}
}
JS:
var db = firebase.database();
var ref = db.ref('tasks');
firebase.auth().signInWithEmailAndPassword("....", "....")
.then(function(userCredential) {
ref.once('value').then(function(snapshot) {
snapshot.forEach(function(childSnapshot) {
console.log(childSnapshot.val());
});
});
});
This will fail with "Error: permission_denied at /tasks: Client doesn't have permission to access the desired data."
If you change var ref = db.ref('tasks'); to var ref = db.ref('tasks/123456'); (123456 being an existing task id) you will get a result.
If you change your rules to the following, the two previous queries will work.
{
"rules": {
"tasks": {
".read": "auth != null",
".write": "auth != null"
}
}
}
2/ How should you do to only get tasks that have user id field as auth.uid?
The first point to note is that "Rules are not Filters", as detailed here: https://firebase.google.com/docs/database/security/securing-data#rules_are_not_filters
So if you implement security rules as follows:
{
"rules": {
"tasks": {
"$taskId": {
".read": "auth != null && data.child('user').val() === auth.uid",
".write": "auth != null"
}
}
}
}
You will need to write a query that includes the same restriction on the user uid, like the following:
var db = firebase.database();
firebase.auth().signInWithEmailAndPassword("....", "....")
.then(function(userCredential) {
var ref = db.ref('tasks').orderByChild('user').equalTo(userCredential.user.uid);
ref.once('value').then(function(snapshot) {
snapshot.forEach(function(childSnapshot) {
console.log(childSnapshot.val());
});
});
});
But this query will not work, again, because "Error: permission_denied at /tasks: Client doesn't have permission to access the desired data."
You cannot do the following neither, since "Shallower security rules override rules at deeper paths.":
{
"rules": {
"tasks": {
".read": "auth != null",
".write": "auth != null"
"$taskId": {
".read": "auth != null && data.child('user').val() === auth.uid",
".write": "auth != null"
}
}
}
}
One solution is to use Query-based Rules (see the doc here) and write your rules as follows:
{
"rules": {
"tasks": {
".read": "auth != null &&
query.orderByChild == 'user' &&
query.equalTo == auth.uid",
".write": "auth != null"
}
}
}
However, as you have probably noticed, this will prevent you to order your query (and filter it) by something else than the user (e.g. by status), since "You can only use one order-by method at a time."
The solution would therefore be to create a second data structure in parallel to your existing structure, where you add the user as a top node, like
"tasks"
"$taskId"
...
"user": "firebase user id"
"tasksByUser"
"$userId"
"$taskId"
...
You would use the update() method to write to the two data structures simultaneously. See the doc here.
I gave .read: true under tasks and it is considering the rules written under the individual task objects before returning the results.

Firebase database rules for particular user

I have a db where I need read access to all users and
write access when invoked in an apps script running by the user =
'firebaseowner#gmail.com'
My firebase structure is
ABC/AAA1/date
ABC/AAA2/date
ABC/AAA3/date
ABC/AAA4/date
The rules are:
{
"rules": {
".read": true,
".write": false,
}
}
How do I make the rule to allow write when invoked by the user 'firebaseowner#gmail.com' in the apps script.
I use https://sites.google.com/site/scriptsexamples/new-connectors-to-google-services/firebase/reference for inserting data
You should check the auth variable.
To define the security rules that allow write access to all the locations by this email address firebaseowner#gmail.com only:
{
"rules": {
".read": true,
".write": "auth != null && auth.token.email == 'firebaseowner#gmail.com'"
}
}
To define the security rules that allow write access to only the location /users by this email address firebaseowner#gmail.com only:
{
"rules": {
".read": true,
"users": {
".write": "auth != null && auth.token.email == 'firebaseowner#gmail.com'"
}
}
}

Allow only read/write of one child

I've been messing around with my firebase database rules to try and allow users without authentication to only edit a certain child in my database, but I can't seem to figure it out.
Here is the database structure:
So I'm trying to allow users without authentication to edit the videoID, but not only that, I need the rule to ignore the room id (5555 in this example), meaning it only allows reading and editing of rooms/(roomid)/videoID
Thanks for all kinds of help!
The Firebase Database rules allow variables and can have different rules at different depths.
In your case, the below rules would allow any users (authenticated or not) to access /rooms/$roomid/videoID but only authenticated users to access the entire /rooms/ tree.
{
"rules": {
"rooms": {
".read": "auth != null",
".write": "auth != null",
"$roomid": {
"videoID": {
".read": "true",
".write": "true",
}
}
}
}
}
The Firebase rule simulator (accessible from the Rules tab of the Firebase Database console) is useful for testing rules before publishing:
Maybe something like this :
{
"rules": {
".read": true,
".write": "auth != null",
"rooms": {
"$roomId": {
"videoID": {
".write": true
}
}
}
}
}
It will allow user with authentification to edit another field beside videoID.
But if you want even authentificated user, also can only edit videoID, then the rule is :
{
"rules": {
".read": true,
".write": false,
"rooms": {
"$roomId": {
"videoID": {
".write": true
}
}
}
}
}
Remember, when the rule set true it will not traverse the child rule, But if it set false it will continue inspect the child rules.

Resources