Reputation: 653
I have the owner role in my firebase project and I am trying to secure my Firestore Database. I want my collections to be secured by default and only accessible if I make a rule for it. I created my database in production mode. However, for some reason even if I specify a rule that allows me to access a collection I receive a Missing or insufficient permissions
error
For example when I register a user I also want to create my own user collection. registering the user works but creating my collection does not work.
register user query (works and adds a user to firebase authentication)
register(value) : Promise<any> {
return new Promise<any>((resolve, reject) => {
this.afAuth.createUserWithEmailAndPassword(value.email, value.password)
.then(res => {
resolve(res);
}, err => {
console.log(err)
reject(err);
})
});
}
Create User collection query (CreateCurrentUserCollection does not work)
public async getCurrentUser() : Promise<any>
{
return new Promise<any>((resolve, reject) => {
let user = this.afAuth.onAuthStateChanged(function(user){
if (user) {
resolve(user);
} else {
reject('No user logged in');
}
});
});
}
public CreateCurrentUserCollection(): void
{
this.authService.getCurrentUser().then(res => {
this.firestore.collection<User>("usersBackup")
.add({
uid: res.uid,
username: res.email
})
});
}
Firebase rules
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users {
allow read, write: if
request.time < timestamp.date(2221, 7, 20);
}
match /usersBackup {
allow read, write: if
request.time < timestamp.date(2221, 7, 20);
}
}
}
if I add the following rule for example
match /{document=**} {
allow read, write: if request.auth != null;
it does work. However then none of my other security rules work, where I want to prevent certain users from accessing certain documents. What am I missing or doing wrong? Please let me know if you need more information thank you in advance.
Update
As noted by Dharmaraj in his answer security rules must point to documents and not collection. This fixes my issue with one of my collection. However I also have a projects collection with an array field called projectMembers. I only want users with a uid inside the projectMembers array to have access to a project document. For some reason It is always giving me Missing or insufficient permissions
error, even if the projects collection is empty.
query
public getProjectsOfUser(userUid: string) : Observable<IProject[]> {
return this.firestore.collection<IProject>("projects", ref =>
ref.where("projectMembers", "array-contains", userUid))
.valueChanges({ idField: 'id'});
}
Firebase Rules
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userID} {
allow read, write: if isSignedIn() && request.auth.uid == userID
}
match /usersBackup/{document=**} {
allow read, write: if
request.time < timestamp.date(2221, 7, 20);
}
match /projects/{projectId} {
allow read, write: if
isProjectMember(projectId, request.auth.uid);
}
//functions
function isSignedIn()
{
return request.auth != null;
}
function isProjectMember(projectId, userId) {
return userId in get(/databases/$(database)/documents/projects/$(projectId)).data.projectMembers;
}
}
}
JWT token send to Firebase by Angular
Upvotes: 3
Views: 366
Reputation: 50830
As mentioned in the documentation,
All match statements should point to documents, not collections. A match statement can point to a specific document, as in match /cities/SF or use wildcards to point to any document in the specified path, as in match /cities/{city}.
If you want users to edit their own document only you should try:
match /users/{userID} {
allow read, write: request.auth != null && request.auth.uid == userID;
}
If not, then you can try adding a recursive wildcard so the rule will be applied for all the documents in that collection:
match /users/{document=**} {
allow read, write: request.time < timestamp.date(2221, 7, 20);
}
Do note that anyone can write to any document if you use the recursive wildcard.
Update: To check if an UID exists in the array.
allow read, write: if request.auth != null && request.auth.uid in resource.data.projectMembers
Upvotes: 2