request.auth.uid seems to always be null in Cloud

2019-07-11 08:07发布

问题:

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!

回答1:

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!



回答2:

You should use firebase.firestore().collection('users').doc(`${currentUser.uid}`).get() instead of firebase.firestore().collection('users').doc(`${email}`).get().

This is because your security rules

match /users/{userId} {
  allow create, read, update: if request.auth.uid != null;
}

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.