Security rules in Firebase - firebase

I've database structure like
appointments
[$userId]
[$appointmentId]
message:"something"
date:"14/12/2015"
users
[$userId]
name: Hardik
email: hardikmsondagar#gmail.com
And I'm using angularfire library of Firebase, I'm trying to restrict read operation based on uid ( means a person who created appointment only can read that). I've tried following security rule
{
"rules": {
"appointments": {
"$userId":{
"$appointmentId":{
".read": "auth.uid==$userId",
".write": true
}
}
},
"users": {
"$userId":
{
".read": "auth!=null && $userId === auth.uid",
".write": "auth!=null && $userId === auth.uid"
}
}
}
But end up on this error
Error: permission_denied: Client doesn't have permission to access the desired data.
I'm trying to access all the user's appointments using following code
var ref = new Firebase("https://<FIREBASE-APP>.firebaseio.com/appointments/"+uid);
$scope.appointments = $firebaseArray(ref);

Set rules for the $uid wildcard, to read all the children.
"appointments": {
"$uid":{
".read": "auth.uid == $uid",
".write": "auth.uid == $uid",
}
}
The $uid wildcard sets permissions for the entire list, whereas the $appointmentId wildcard sets permissions for each individual item.
But Security Rules cascade, so you only need to set the rules for the top level.
Read the docs on cascading for more information.

Related

Firebase Realtime Database user data access based on uid

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.

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"
}
}

Securing a location in firebase database for one or more users to write to

I'm building a new application using firebase authentication and realtime database. I understand how to secure a location in the database so that only a specific authenticated user can write to it, as per the documentation:
{
"rules": {
"users": {
"$user_id": {
// grants write access to the owner of this user account
// whose uid must exactly match the key ($user_id)
".write": "$user_id === auth.uid"
}
}
}
}
I want to secure a location for one or more users. I'm not sure whether that is possible and if so, how would I structure the data. The data is a list of shopping items that one or more users can update, while all other users can view the shopping items. All users are authenticated, but one or more of them is designated as the shopper, so they are allowed to add and remove items.
Thanks
Craig
Just in case someone stumbles across this, a member of the firebase forum was able to answer the question and I ended up with the following database rules:
{
"rules": {
"users": {
".read": "auth !== null",
"$udser_id": {
".write": "$user_id === aith.uid"
}
},
"shops": {
"$shopID": {
"items": {
".read": "auth != null",
".write": "data.parent().child('shoppers').child(auth.uid).exists()"
},
"shoppers": {
".read": "auth != null",
".write": "root.child('users').child(auth.uid).child('scheduler').val() == true || data.child(auth.uid).exists()"
},
"boxes": {
".read": "auth != null",
".write": "auth != null"
}
}
}
}
}
This was based on an article here: https://firebase.googleblog.com/2016/10/group-security-in-firebase-database.html

Firebase Security Rules Correct Format

Are these rules in correct format? When I put them in Database Rules, I see red dashed lines which may indicate an error/warning but when I hover over it, I receive no feedback.
{
"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",
// grants read access to any user who is logged in --&& auth.provider === 'password'
".read": "auth !== null"
}
},
"usernames": {
"$userName": {
// grants write access to the owner of this user account whose uid must exactly match the key ($uid)
".write": "root.child('usernames').child($userName).child('uid').val() == auth.uid || root.child('usernames').child($userName).child('uid').val() == null",
// grants read access to any user who is logged in --&& auth.provider === 'password'
".read": "auth !== null"
}
},
"following": {
"$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",
// grants read access to any user who is logged in --&& auth.provider === 'password'
".read": "auth !== null"
}
},
"followedBy": {
"$fid": {
"$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",
// grants read access to any user who is logged in --&& auth.provider === 'password'
".read": "auth !== null"
}
}
}
}
}
This is what I see:
To reformat your code rules and make it read able
Just copy your rules and then go to JS cleaner and click claen Js re copy and past into your database rules
I've seen those too. Pretty much as soon as I add an empty line.
I think the empty lines are just causing a false error indicator to show up.
Since nothing's failing (at least not for me as far as I can see), I wouldn't worry about them.

Firebase security rules, setting a children not readable?

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'"
}
}
}
}

Resources