2
    firebase.initializeApp(config);
    const db = firebase.firestore();

   const googleSignIn = async () => {
        return await Expo.Google.logInAsync({
            androidClientId,
            iosClientId,
            scopes: ['profile', 'email'],
        });
    };

    const firebaseLogin = async (accessToken) => {
        const cred = firebase.auth.GoogleAuthProvider.credential(null, accessToken);
        await firebase.auth().signInWithCredential(cred).catch(console.error);
        const idToken = await firebase.auth().currentUser.getIdToken(true).catch(console.error);
    };

await firebaseLogin(googleSignIn().accessToken);
db.collection("any").doc().set({test: "OK"})

I get a permission denied error when trying to write to Firestore using a request.auth.uid != null; security rule, but when I replace it with true it works.

It seems that the Firestore component of the web SDK does not send authentication details, even though the API on the client reports Firebase is logged in, and the user last login date appears in the web GUI.

Do I need to pass authentication details to the Firestore component when logging in directly with Google (instead of using the Firebase login APIs)?

The code is running in a React Native app via Expo.

Another example that gets a permission denied:

firebase.auth().onAuthStateChanged((user) => {
    if (user) {
        firebase.firestore().collection("any").doc().set({test: "OK"});
    }
});

Rules

// This is OK:
    service cloud.firestore {
      match /databases/{database}/documents {
        match /any/{doc} {
            allow read, write: if true;
        }
      }
    }

// Permission denied
    service cloud.firestore {
      match /databases/{database}/documents {
        match /any/{doc} {
            allow read, write: if  request.auth.uid != null;
        }
      }
    }

Related

zino
  • 1,222
  • 2
  • 17
  • 47
  • Auth works fine with Firestore. However, your code doesn't reveal very much of what you're doing. Nothing happens with `db`. – Doug Stevenson Feb 24 '18 at 23:22
  • Code is just to show how I am logging in, have updated. – zino Feb 24 '18 at 23:29
  • Have you tried using an auth state listener to find out when the SDK knows for a fact that your credentials are ready? FYI you are also not passing a string to `doc()`. – Doug Stevenson Feb 24 '18 at 23:34
  • doc() without an argument means "auto-create an ID" – zino Feb 24 '18 at 23:40
  • Please show your exact security rules. – Doug Stevenson Feb 24 '18 at 23:42
  • 1
    I am encountering the same issue as Zino n i m also using expo. someone posted on this as well. I havent tried downgrading expo to test it out https://stackoverflow.com/questions/48054884/firebase-firestore-missing-or-insufficient-permissions-using-expo-react-native – Hendry Lim Feb 26 '18 at 11:40
  • I'm currently facing the same issue using the Web SDK. I'll post back if I find anything. – Mapsy Apr 26 '18 at 15:07

1 Answers1

0

This solution, and possibly this whole issue, may be specific to React Native.

In a similar question, Jade Koskela noticed that requests were missing the Origin header, and applies a patch to React's XHRInterceptor to work around the missing auth object:

const xhrInterceptor = require('react-native/Libraries/Network/XHRInterceptor');
xhrInterceptor.setSendCallback((data, xhr) => {
  if(xhr._method === 'POST') {
    // WHATWG specifies opaque origin as anything other than a uri tuple. It serializes to the string 'null'.
    // https://html.spec.whatwg.org/multipage/origin.html
    xhr.setRequestHeader('Origin', 'null');
  }
});
xhrInterceptor.enableInterception();
Mapsy
  • 4,192
  • 1
  • 37
  • 43