I must be missing something really basic here... but any time I make a call to my Cloud Firestore db and I try to institute any kind of rules for security, they always fail.
Doing something like
match /users/{userId} {
allow create, read, update: if true;
}
works, but it obviously defeats the point. However, if I do any kind of additional scrutiny, such as the go-to example in all the docs like
match /users/{userId} {
allow create, read, update: if request.auth.uid != null;
}
it fails every time. Am I missing something obvious in how I'm wiring together my client side code?
Here's my client side code that logs the user in, and then makes a call to the db to grab a user. (Note that in my db the keys for the users are by email, not by uid)
// this is a snippet from the code where I log the user in
firebase.auth().signInWithEmailAndPassword(email, FIREBASE_USER_PASSWORD)
.then(user => {
// the user comes back successfully logged in,
// I grab its uid and add it to a preparedUser object that I've been building,
// then pass this user to my getFirestoreUserObject function
preparedUser.uid = user.uid;
getFirestoreUserObject({dispatch, user: preparedUser, navigate});
})
// then the getFirestoreUserObject function:
// note that all the code below works fine when there are no security rules in place
const getFirestoreUserObject = ({dispatch, user, navigate}) => {
const {name, email, imageUrl} = user;
// if I ask for currentUser here, I get back my logged in user
const currentUser = firebase.auth().currentUser;
// email is defined correctly here as the user's email
firebase.firestore().collection('users').doc(`${email}`)
.get() // the request fails here due to insufficient permissions
.then(doc => {
if (doc.exists) {
const currentUser = doc.data();
getUserFavorites({dispatch, currentUser, navigate});
} else {
createUserInFirestore({dispatch, user, navigate});
}
})
};
Is there something obvious that I'm missing? If I log a user in via firebase.auth()
, and then immediately after call firebase.firestore()
, shouldn't that have the context of the auth'd user? If not, how do I pass it to the firestore call?
Thanks!
You should use
firebase.firestore().collection('users').doc(`${currentUser.uid}`).get()
instead offirebase.firestore().collection('users').doc(`${email}`).get()
.This is because your security rules
check for the uid of the user when determining whether or not to provide access to the data to the user, not the user's email.
Hope that helped.
After weeks of searching, and firestore and auth both working independently but not together... it was the most simple thing.
I was on firebase 4.x, which was the latest available when I started my project. Then, when I came around to adding auth rules, the latest published documentation on firebase for how to do the db rules (which I hadn't even looked at when I started, but came back to months later when I was ready to implement them) were listed using firebase 5.y. Updated my package.json, npm install, and everything magically worked :(
Hope this can help someone else... make sure you're on at least version 5!