Firstore database rule 'request.auth.uid' not working - firebase

Can someone help to solve why this firestore rule is not working. Am I missing something simple ??
If you look at the clip below you see my rule for /users/{userId} is allow read: if request.auth.uid == userId; BUT THE SIMULATION FAILS , and my chrome console also confirms "Missing or insufficient permissions"

You can't use wildcards for document locations like that in the simulator. Your "Location" string on the left should identify a single document.
Also, if you want to test authentication, you will need to provide a UID to test with in the "Firebase UID" field.
In your case, you will want to test using the same UID string value in both the document location and the UID fields.

Related

Firebase how check path contains value and allow read and write other path

At the moment i try to build a chat in flutter with google firebase.
Now i would like my database more secure.
That means only users (room_3) in chat can read and write data data.
Is it possible to check a path contains a user value
and if the user value is contains allow read a other path?
Here my database structer:
/chat/product_id/product_id_12345/chat_room_id/room_1/message_1/message2...
My idea is i add in 'room_1' the user id.
Then i check the user is contains in 'room_1'.
If the user is contains i allow read and write data the complete path (message_1/message_2...).
Here my example:
If you have any questions fell free to ask me.
Many thx.
In the security rules for the messages subcollection you can read the parent document and check whether the current user is in the user_id field with:
...
match /messages/{message} {
allow read:
if request.auth != null &&
request.auth.uid in
get(/databases/$(database)/documents/chat_room/$(chat_room_id)).data.user_id
}

Firestore security rule get vs. list

Suppose I'm trying to make a webpage readable only when the user has the exact link to it, could I achieve this using a combination of the document ID and security rules as follows?
eg. I have documents stored at
/posts/{postID}
I have security rules set up:
match /posts/{postID} {
  allow get, write: if true;
  allow list: if false;
}
Would simply disabling the "list" operation make it such that you can only access a document if you already know its exact ID? It looks like the case to me but I'm not sure if I'm missing any edge cases.
Would simply disabling the "list" operation make it such that you can
only access a document if you already know its exact ID?
Yes, this is right.
Any query to the posts collection will return a "Missing or insufficient permissions" error, even a query that queries with the exact ID, like:
firebase
.firestore()
.collection('posts')
.where('__name__', '==', 'exactID')
.get()

Firebase auth uid not interpreting the actual value

I see a similar issue in Firebase User UID not matching Auth UID,
however mine is slightly different, instead of comparing the key in the path I am trying to compare the value with the auth.uid.
It looks like a bug according to my testing, I tried to log it with Firebase, but Andres replied that comparing the data values is not the way to work the rules.
The data is stored with the Key "id" which has the value 455, if I hard code 455 in the rules, it works fine. If I reference "äuth.id" it fails. I can tell auth.id is failing because if I test with a different function such as hasChild('auth.id') it works fine, I am using this as a workaround for now.This is on the Realtime database with rules v2.
In all tests I am trying to do a read at /test
Data:
test
|-677
| |-jf:"golf"
|-ff:"tennis"
|-id: 455
Auth token :
{
"provider": "anonymous",
"uid": "455"
}
Rule that fails which should have passed :
read: "data.child('id').val()==auth.id"
Rule that works hard coded:
read: "data.child('id').val()==455"
Rules that works indicating the value in auth.id is correct
read: "data.child('id').val==455 && root.child('test').hasChild(auth.uid)"
read: root.child('test').hasChild(auth.uid)"

Unable to base security rule condition on resource data in Firebase

I am attempting very simple thing and that is matching request.auth.uid to a field value in my transaction documents (like this resource.data.useruid) in Firebase security rule in order to get transactions of a particular logged in user. However, I don't get any documents while querying for them and get an error instead.
This is how the collection looks like - just one document there with useruid field.
The field's value is mapped to the users uid (screenshot taken in the Authentication -> Users tab.
And the rule looks like this
I should get the one document back but every time I query the documents with that user logged in (I am using angularfire2 for those purposes) I get Error: Missing or insufficient permissions.
If I modify the rule condition to return always true or if I only check for truthiness of request.auth.uid I get the query result alright. The funny thing though is that with resource.data involved - eg. checking for value of the amount field in the firebase rule - the condition is never met. I tried to write it like
allow read, write: if resource.data.amount == 3
and got the error again. Seems like I don't get the resource.data Map at all.
I feel like I am missing something obvious, although after reading the guides, it seems alright to me and I am already out of ideas. The debugging capabilities (or lack of) make the whole process very slow.
Could you please explain to me, why I don't get the resource.data Map in the firebase security rule or point me to a place where the problem might be?
You have most probably missed one specific point in the doc: your query fails "because it does not include the same constraints as your security rules". See https://firebase.google.com/docs/firestore/security/rules-query#secure_and_query_documents_based_on_authuid
The following, with your security rules works perfectly:
firebase.auth().signInWithEmailAndPassword("xxxx#xxxx.com", "xxxxx")
.then(function (info) {
db.collection("transactions").where("userid", "==", info.uid).get().then(function(querySnapshot) {
querySnapshot.forEach(function(doc) {
console.log(doc.id, " => ", doc.data());
});
});
});
If you remove the where clause, you get the exact error you are getting

Firestore Security Rules: If timestamp (FieldValue.serverTimestamp) equals now

How do I check if user on client sided created document with only firebase.firestore.FieldValue.serverTimestamp()?
I have following:
allow create: if request.resource.data.timestamp == ??
What should I have instead of ??. I have tried serverTimestamp() firebase.firestore.FieldValue.serverTimestamp(), now or now() but it doesn't work.
It is possible to do it in Firebase like this:
".validate": "newData.child('timestamp').val() === now"
I am looking for the same solution. Any ideas? Thanks
You can access the current request timestamp in Security Rules using the request.time attribute (docs), which is the Firestore equivalent to the Realtime Databases's now. You'll therefore want something like:
allow create: if request.resource.data.timestamp == request.time;
For serverTimestamp() this should evaluate to true.
You should always validate client input in Security Rules, even if you're using serverTimestamp(). Security Rules doesn't automatically know the server input the value instead of the client, so without this check, a malicious client could create a different created at time.

Resources