How strict Firestore Rules have to be? - google-cloud-firestore

Can I trust the data that are coming in the Firestore, or do I have to check everything and absolutely not trust the incoming data, because client can fake everything?
For example, can client fake uid, email and display name?
firebase.firestore().collection("users").doc(state.user.uid).collection("friendRequests").doc(payload.uid).set({
uid: payload.uid,
email: payload.email,
displayName: payload.displayName
});
Firestore rules:
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read;
}
match /users/{userId} {
allow read, update, delete: if request.auth.uid == userId;
allow create: if request.auth.uid != null;
}
match /users/{userId}/friendRequests/{friendId} {
allow create: if userId == request.auth.uid
&& friendId != request.auth.uid
&& !exists(/databases/$(database)/documents/users/$(request.auth.uid)/friends/$(friendId))
&& !exists(/databases/$(database)/documents/users/$(request.auth.uid)/friendRequests/$(friendId))
&& !exists(/databases/$(database)/documents/users/$(friendId)/friends/$(request.auth.uid))
&& !exists(/databases/$(database)/documents/users/$(friendId)/friendRequests/$(request.auth.uid));
}
}
}
Set of rules is already quite big and I didn't even check yet if the data structure is valid and if friend uid exists.

The request.auth in your security rules is populated by Firebase Authentication. That means that the user triggering the rules must have signed in with Firebase Authentication, and that the profile in request.auth is belonging to the user that signed in.
The only way someone can hijack that process is if they get access to the administrative credentials for your project. With that they can generate any tokens they want. But if this happen, they can already access your database without restrictions, so the additional step of forging a token is rather useless.
Of course when using a social provider (Facebook, Github, Google, etc) users can set whatever display name they want. So you typically should not depend on that being valid, beyond using it to display a name for each user.

Related

Flutter Firestore Security Rules

I've been trying to get the Firestore rules to play nice for a while now and every time I think I get them right, another portion stops working for some reason.
I'm trying to have some simple rules, if you made the document that document and any child documents or collections, you can create, edit and delete them. I thought this was pretty simple but alas I keep getting permission denied errors.
Rules:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
allow read, update, delete: if request.auth != null && request.auth.uid == userId;
allow create: if request.auth != null;
}
match /users/{userId}/{document=**} {
allow read, update, delete: if request.auth != null && request.auth.uid == userId;
allow create: if request.auth != null;
}
}
}
When doing just the match /users/{userId} I was able at one time able to create user documents but I couldn't create child documents or colletions.
When doing just the match /users/{userId}/{document=**} I could no longer create users but any existing users I could add child documents and collections and do everything expected.
This combination of both rules doesn't seem to work either.
I keep getting [cloud_firestore/permission-denied] The caller does not have permission to execute the specified operation. when I try to create a user with this statement:
await FirebaseFirestore.instance.collection('users').doc(googleUser.uid).set(
{
'created': now,
'lastLogin': now,
'name': name,
'email': email,
},
);
Now nothing works. I deleted all my authentication accounts and my Firestore data and wanted to start over but it simply will not create the data in Firestore.
Any suggestions would be greatly appreciated as I'm going in circles and nothing is working anymore which is extremely frustrating as it did at one point but no longer does.
edit All of my testing is being done on a real Android phone.
After walking away from my computer and thinking more, I figured out what it was. My App Check debug token changed somehow.
Once I added the new value from the debug console everything started working again.
I'll leave this answer here in case this saves anyone else some headaches in the future!
Edit: Additionally, ones App Check debug token will change anytime you clear storage on your app on the device. Which is why mine was changing.

Can't access Firestore after etting "allow all authenticated"

I'm initializing FireStore in my Chrome extension like they explain in the docs:
import { initializeApp } from "firebase/app";
initializeApp({apiKey:'...', ...});
Then I call setDoc to store a document. Everything is fine when I set allow read, write: true in the access rules. But when I change it to allow read, write: if request.auth != null, all my Firestore requests start failing with Error adding document: FirebaseError: [code=permission-denied]: Missing or insufficient permissions.
I assumed that providing my Firestore API key and other data in the initialization code would automatically make it authenticated. However, Firestore thinks that my requests are anonymous for some reason. How do I fix this?
Here's my config:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth != null
}
}
}
The request.auth check if the request is coming from authenticated user in firebase authentication.
The Firestore API key is only to send the request to the correct firebase project, but it doesn't make the request.auth != null.
You need to authenticate against firebase authentication in order to get request.auth != null. But in your case I beleive you don't want the users to authenticate, so you need some other security rule to get what you really want to check.

Insecure rules in firebase

I understand it's not good to set your read and writes to all users on Firebase;
But what if you leave your reads to all and your writes to only authenticated users?
What is the worst thing that could happen?
Is it easy for someone to gain access to the firebase project?
I'm currently using cloud firestore.
Sorry if this seems a little dumb, I'm new to this:
Thanks,
Jacob
EDIT: Current Rules:
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read: if true;
allow write: if request.auth != null;
}
}
}
I've worked with Firebase for a long time and I've come to realize that the rules are a very good way to prevent unauthorized access to your data, by any third party - especially when used in tandem with rules set within your Application (be it Web, iOS or Android).
Personally, I usually set my rules to the following:
service cloud.firestore {
match /databases/{database}/documents { match /{document=**} {
allow read, write: if request.auth != null;
}
This means that only logged in users are allowed to access the data and write data as well.
If, instead, you want users to access the data without being logged in but only write data if they're logged in, then I would suggest these rules:
service cloud.firestore {
match /databases/{database}/documents { match /{document=**} {
allow read;
allow write: if request.auth != null;
}
In terms of how easy it is to access a Firestore Database when not authorized to:
Google has done a good job at keeping things secure.
Setting up these rules and some other checks within your Application is enough to keep things secure.

Basic Cloud Firestore security rules setup

I am currently using this default code to secure my Cloud Firestore database:
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if request.auth.uid != null;
}
}
}
This code works fine and the simulation is fine.
I tried to update the code and use the new default code I find in every guide:
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth.uid != null;
}
}
}
But this code fails every time, the access is not granted.
In the simulation, I just try to read a document in a Collection named "parameters".
Am I missing something here? My plan is to harden the security access afterwards.
Ok my bad, I actually realised that the database access rules and the storage access rules have their own and separate security panels.
I was trying to update the storage rules with the default database rules...

Firestore Security Rules: Insufficient permissions

I need some help making my security rules for firestore work.
These are my firestore rules:
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
function isAdmin(uid) {
return (uid in get(/admin/administrators).data.uid)
}
allow read;
allow write: if request.auth.uid != null && isAdmin(request.auth.uid);
}
}
}
In document /admin/administrators there is a field named uid containing an array of UIDs of administrators which are allowed to write in the database.
After I logged in as one such administrator and tried to add a document to another collection. (Specifically, the call in my Angular application using Angularfire 2 is this.afStore.collection(collection).add({});) I received the error Error: Missing or insufficient permissions.
Any help appreciated (including "there's obviously a better way to do this")
You should enter the absolute path of the collection you're trying to reference. Change the (uid in get(/admin/administrators).data.uid) to get(/databases/$(database)/documents/admin/$(request.auth.uid)).data.uid