So, I typically don't have problems writing firestore rules but I'm coming up short on why this simulation fails.
If you don't want to follow the image link:
Rules:
service cloud.firestore {
match /databases/{database} {
match /server_credentials/{document = **} {
allow read, write: if false;
}
match /users/{user_uid} {
allow read, write;
match /signatures/{sig_id} {
allow read: if request.auth.uid != null && resource.data.access == "public";
allow read, write: if request.auth.uid == user_uid;
}
match /identity/{credential} {
allow read, write: if request.auth.uid == user_uid;
}
}
match /signatures/{sig_id} {
allow read, list;
allow write: if false;
}
}
}
Auth details:
Google as provider and foo as the uid.
I'm testing a simple read to users/foo
Any help would be quite nice.
This line is incorrect:
match /databases/{database} {
It should be this:
match /databases/{database}/documents {
This mistake is causing none of your rules to apply at all, and all access is being rejected by default.
Related
I Have Created firebase and flutter app and google is sending me emails saying firebase rules are not good. How do I make those rules better? I want to give permission to login users to read and my account to read and write permission.
I hope that will help you.
service cloud.firestore {
match /databases/{database}/documents {
// Make sure the uid of the requesting user matches name of the user
// document. The wildcard expression {userId} makes the userId variable
// available in rules.
match /users/{userId} {
allow read, update, delete: if request.auth != null && request.auth.uid == userId;
allow create: if request.auth != null;
}
}
}
This is a correct way you can secure database.
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// Line below secure whole database so users are not alowed to create any new collections etc.
match /{document=**} {
allow read, write: if false;
}
match /app/{dataId} {
allow read: if true;
allow write: if isAdmin();
}
match /posts/{dataId} {
allow read: if resource.data.isPublic == true || isAdmin();
allow write: if isAdmin();
}
}
}
function isAdmin() {
return request.auth.token.admin == true;
}
Users don't have any .admin variables. You have to assign them using firebase functions. Read about custom claims.
I have written some firebase rules, using firebase emulator. I tried to debug the request which I am sending to the rules, using debug() function. Yet it doesn't print anything. My rules:
function printResource() {
return debug(resource) || true;
}
match /users/{userId} {
allow read, delete: if something....;
allow create: if printResource() && userIsAuthenticated() && userOwnsResource(userId) && debug(isUserNameAvailable(debug(request))) && getAfter(
/databases/$(database)/documents/usernames/$(request.resource.data.username)
).data.owner == userId;
}
I tried as well the following:
match /users/{userId} {
allow read, delete: if something....;
allow create: if debug(userIsAuthenticated()) && debug(userOwnsResource(userId)) && debug(isUserNameAvailable(debug(request))) && getAfter(
/databases/$(database)/documents/usernames/$(request.resource.data.username)
).data.owner == userId;
}
Nothing is being printed. My debug() function is not working, but I don't know why. Is there another way I can print my resource object?
Im trying to figure out how the rules in Firestore work, and have stumbled upon a problem I cant quite figure why is failing.
When using the Firestore Rules Playground and do a get request for a document in /apps, I get the following error: "Error running simulation — Error: simulator.rules line [10], column [14]. Null value error."
And from the app im getting: FirebaseError: Missing or insufficient permissions
The location in trying to get: "/apps/0aKQw0MiRzEbrLDvsnI3"
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if isUserAuthenticated();
}
/* Functions */
function isUserAuthenticated() {
return request.auth.uid != null;
}
}
}
The thing im trying achieve is to allow read access for all document, and only write access if a user is signed in
I have no idea why it's failing on a get request?
If I'm not mistaken the way you added the read condition seems to be incorrect. Perhaps try this and see if it works for you.
match /databases/{database}/documents { match /{document=**} { allow read: if true, write: if request.auth != null && request.auth.uid!=null }
Question:
For the different top-level firestore collections below, how to restrict access to all but one of the paths?
We are building a data schema in Firestore to support a chat app for teachers across multiple schools.
The top-level firestore collections include:
/siteAdminUsers
/schools
/schools/{schoolId}/teachers
/schools/{schoolId}/chats
Below is the security rules setup we are trying now - where we check for:
valid user auth
expected value exists in userClaim variable request.auth.token.chatFlatList
However, the read listener for /messages is being blocked.
Error message:
FirebaseError: [code=permission-denied]: Missing or insufficient permissions
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if false;
}
match /schools/{schoolId}/chats/{discussionId}/messages {
allow write: if false;
allow read: if request.auth != null
&& request.auth.token != null
&& request.auth.token.chatFlatList.val().contains($discussionId);
}
}
Details
We are using cloud functions for all data read/write, so for almost every case we can just block all client access.
The one exception is for the chat discussions, where we need to set a snapshot listener in the mobile client to know when there are new messages.
Sub-collection notes:
At a school, there are discussion sessions for school staff (teachers, admins, etc)
/schools/{schoolId}/chats/{discussionId}
Where each discussion-document contains:
list of participant teacher ids
subcollection for actual messages where each document is an indivual posted message:
/schools/{schoolId}/chats/{discussionId}/messages
User Claim code from Cloud Function
Looking at the cloud function logs, we have verified that the userClaim is being set.
return firebaseAdmin
.auth()
.setCustomUserClaims(
uid, {
chatFlatList: 'id1 id2 id3'
}
);
UPDATE #1
Tried the following variation where rules skip/omit the check on userClaim and auth.token.
However, still same permission error.
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if false;
}
match /schools/{schoolId}/chats/{discussionId}/messages {
allow write: if false;
allow read: if request.auth != null;
}
}
}
I think the issue here is that you are writing a rule on the collection called messages.
All match statements should point to documents, not collections.
https://firebase.google.com/docs/firestore/security/rules-structure
You should try adding /{document=**} after your path to messages, something like:
match /schools/{schoolId}/chats/{discussionId}/messages/{document=**} {
allow write: if false;
allow read: if request.auth != null;
}
This worked for me if I wanted to read and write all collection but not one collection named "backStage";
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{collection}/{document} {
allow read: if true
allow write: if (collection != "backStage");
}
}
}
Here's a solution (seems to be working), which includes the check on chatFlatList user claim variable (from original question) for a substring :
match /schools/{schoolId}/chats/{discussionId}/messages {
allow write: if false;
allow read: if request.auth != null
&& request.auth.token.chatFlatList.matches(discussionId);
}
Figured this out thanks to:
Firebase storage rules based on custom parameters
Here the post shows there is not any $ notation to access the path var. I recall seeing this in a security rules example code example - maybe it's specific to database tiers?
https://firebase.google.com/docs/reference/security/storage/#string
https://regex-golang.appspot.com/assets/html/index.html
Trying some example inputs here, to get an understanding for how to create the regex's.
I'm currently using Firestore for database and ran in to insufficient permission error. What I don't understand is why isPartner() will work when my path is
users/{uid}
but give me permission error when it's
object/{objectID}
Security Rules
service cloud.firestore {
match /databases/{database}/documents {
match /users/{uid} {
allow read: if isSignedIn();
allow write: if isOwner(uid) || isPartner();
match /object/{objectID} {
allow read, write : if isPartner() || isOwner(uid);
}
function isOwner(userID) {
return request.auth.uid == userID
}
function isPartner() {
return resource.data.partnerUID == request.auth.uid
}
}
}