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

2019-07-11 07:14发布

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!

2条回答
别忘想泡老子
2楼-- · 2019-07-11 07:56

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.

查看更多
贼婆χ
3楼-- · 2019-07-11 08:12

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!

查看更多
登录 后发表回答