Firebase realtime db + nodejs (auth.uid === $uid rule) - firebase

I am trying to use fetch to access /userInfo collection and I have the following rules in firebase:
"rules": {
"userInfo": {
"$uid": {
".read": "auth.uid === $uid",
".write": "auth.uid === $uid"
}
}
I was trying to extend the default user profile and saw that I need to create collection and add the additional data there so my collection is "userInfo".
Now I am trying to restrict user of fetching other users information so he cannot do something like:
fetch(db.firebaseio.com/userInfo.json)
and get all the information about all users.
So the problem is when the rule is "auth !== null" I can simply add "?auth=" + token at the end of the url to auth, but it doesn't work the same way for auth.uid.
I wonder what should be the query parameter when sending the request so I can tell to firebase what my user.uid is?
Attaching postman screenshot for better understanding of the problem:
Postman request
Attaching also DB struct from Firebase:
DB Structure
Request with token:
Postman request with token also gives permission denied for this rules

Related

User get 401 when trying to fetch data from firebase realtime database

I am using REST API in my vuejs app to access firebase realtime database, I authenticate users using Google provider and get access token.
Whe I try fetching data using access_token https://rtdb-url/uid/products.json?access_token=[access token] user get 401 error.
But if the user was added to "Users and permissions" in project settings it works.
Rule appplied to RTDB
{
"rules": {
"$uid": {
"products": {
".write": "auth != null && $uid === auth.uid",
".read": "auth != null && $uid === auth.uid"
}
}
Apparently, I just needed to use the access token I got and send it to the following endpoint in the POST body:
https://identitytoolkit.googleapis.com/v1/accounts:signInWithIdp?key=
As described in the documentation.

Firebase auth database rules

I am working on the app that I need to connect to the dev firebase.
This firebase has database rules as follows:
"rules": {
// no read access at root level
".read": "auth.uid === 'emailaddressgmailcom'",
".write": false,
What I cannot understand is how auth.uid is specified to be an exact email address?
As far as I tried I only get unique uid provided by Google. (set of numbers and letters)
Hence I can never pass the auth to read from the database, unless I specify my exact uid given by Google in the databse rules, which is not an option because there will be another user who needs an access to db and I do not know his uid.
auth is one of the predefined variables.
By doing auth.uid, you get the user id ("guaranteed to be unique across all providers").
You need, in your Security Rules to use it to defined the access rights of a given user to one or more given resources, as explained here in the doc.
You could compare it to a fixed value, if a certain resource shall be read by a unique user:
".read": "auth.uid === 'HGH656675FHGFGHF3454'"
but usually you compare it to some parts of the path of the node/resource you want to protect, like for example:
{
"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"
}
}
}
}
This is how you should do to solve your problem "there will be another user who needs an access to db and I do not know his uid".
I would suggest you read the entire section about RTDB Security Rules form more details: https://firebase.google.com/docs/database/security
Please try below rules
{
"rules": {
"users": {
"$uid": {
".read": "$uid === auth.uid",
".write": "$uid === auth.uid"
}
}
}
}
// These rules grant access to a node matching the authenticated
// user's ID from the Firebase auth token

How to access parent auth status in array

I'm not sure whether the title of this is appropriate as I'm new to Firebase Authentication and rules, however, I have successfully setup authentication and am now trying to protect a particular route and can't seem to access the relevant data, here's my Firebase rules on my realtime database:
{
"rules": {
"accounts": {
"$uid": {
".read": "$uid === auth.uid",
".write": "$uid === auth.uid"
}
},
"demo": {
".read": "accounts.$uid === auth.uid",
".write": true
}
}
}
As you can see, I'm trying to access the accounts/$uid/ from within "demo", it doesn't seem to work, what am I missing/what do I need to change?
Many thanks
UPDATE
The code in question not working is:
".read": "accounts.$uid === auth.uid"
I can't seem to access this part. It doesn't seem to get the current user's authentication status.
UPDATE
See attached screenshot for my attempt on using a predefined variable. I'm simply trying to get the auth status and I'm getting an error saying it's undefined?
The UID of the current user who is trying to access the data is available in auth.uid. If you're trying to ensure that a read of quotes is only allowed if the user has a document in the accounts node, you're looking for exists().
"website-quotes": {
".read": "root.child('accounts').child(auth.uid).exists()"
}

How to simulate the firebase database rule with firebase auth that have a registered email

I am new to firebase and I am trying the firebase database rule and firebase auth.
I trying to use the firebase auth for firebase database rule.
So I have create a demo email to test this the database rule.
email : abc#gmail.com
uid : WfipZwUuNvTIkRYvPxsFqzd1rag2
My database rule (followed the firebase site) https://firebase.google.com/docs/database/security/user-security
Firebase Database Rule :
{
"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",
".read" : "$user_id == auth.uid"
}
}
}
}
I have tried to use the simulator for the database rule with the below custom payload with authenticated and couldn't access the read or write.
Payload :
{
"provider": "password",
"uid": "WfipZwUuNvTIkRYvPxsFqzd1rag2"
}
So what am I missing in this point?
Updates
What I need is use the firebase authenticate email to give a read and write access to the database.
I am currently trying on the firebase database rule simulator.
I keep getting access denied. So maybe is my payload is not right for the authentication. Need HELP!!!
i tried the rules that you specified in ths simulator and i got simulated write allowed the only difference is i didn't use the uid that you specified.
See Below Images for result
As per documentation you should implement:
{
"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",
".read" : "$user_id === auth.uid"
}
}
}
}
Notice you should implement '===' instead of '=='
The above implementation will allow only user WfipZwUuNvTIkRYvPxsFqzd1rag2 to read and write on that specific location "/users/{user_id}"
Updates
I tested and it works this time. Last time i tried the rule did not work that is very weird.
Ok, I assume the simulator's authenticated means if any of my firebase auth user is logged in.
So, my path and my rules have problems during the test and is not my payload
If I want to allow the database access by the firebase auth user then my rule should be like this (I presume).
Rule: for fire base auth to access the whole database with read and write permission.
{
"rules": {
".write": "auth.uid != null",
".read" : "auth.uid != null"
}
}
Thanks #d.mares and #MuruGan

Firebase database rules: users permission

I want to make different permission for different user roles.
For example, when the user is not super-owner, don't let him write in my items table.
This is what I tried to do:
{
"rules": {
"items": {
".write": "auth.authority == 'super-owner'"
}
}
}
But I notice that the authority field is stored in my users node I created on my own and is releated to the Firebase auth. How I can access users->authority of current logged in user through the rules?
Update: I did try this:
".read": "root.child('users/'+auth.uid).authority.exists()",
but I get Error saving rules - Line 10: No such method/property 'authority'.
You get this error because root.child('users/'+auth.uid) returns instance of DataSnapshot which does not have authority property of course. But it has hasChild method.
For full list of methods about DataSnapshot visit the following link.
https://firebase.google.com/docs/reference/js/firebase.database.DataSnapshot.
Try this.
".read": "root.child('users/'+auth.uid).hasChild('authority')",
".write": "root.child('users/'+auth.uid).hasChild('authority') && root.child('users/'+auth.uid+'/authority').val() == 'super-owner'"
or this
".read": "root.child('users/'+auth.uid+'/authority').exists()",
".write": "root.child('users/'+auth.uid+'/authority').exists() && root.child('users/'+auth.uid+'/authority').val() == 'super-owner'"
or the shortest version
".read": "root.child('users/'+auth.uid+'/authority').val() !== null",
".write": "root.child('users/'+auth.uid+'/authority').val() == 'super-owner'"

Resources