My use case is, I have a web app in which I listen to Firestore collections. One of the collections are for public users where anonymous auth is enough. And the second collection is for logged in users, so I implemented custom token auth following this. https://firebase.google.com/docs/auth/web/custom-auth. Once a user logs in, we start a Web Worker to initialise app and listen to Firestore.
My problem is, when a user logs in, the second subscription, the authenticated one, works, but if I try to go to public page, where I don’t need the auth token, from the same tab, I get this error.
Uncaught (in promise) FirebaseError: Missing or insufficient permissions. at new Ur (prebuilt.js:184:9) at prebuilt.js:10612:34 at br.<anonymous> (prebuilt.js:10564:21) at Bt (eventtarget.js:351:23) at qt (eventtarget.js:481:26) at Ir.wa (webchannelbasetransport.js:369:17) at Ke (webchannelbase.js:2258:25) at Fe (channelrequest.js:951:12) at Ne.N.Ia (channelrequest.js:743:10) at Ne.N.gb (channelrequest.js:603:10)
Both subscription uses the same firebase app, same configs.
More Info:
these are the rules
function isSignedIn(){ return request.auth != null; } function isDocumentOwner(docid) { // checks if user id is the same as the document id return isSignedIn() && request.auth.uid == docid; } //this collection can be accessed for guest/anonymous users match /guests/{uid} { allow read, write: if isDocumentOwner(uid); } //this collection in only accessible for logged in users(JWT token) match /users/{uid} { allow read, write: if isDocumentOwner(uid); }
And this is the init codes
Guest page:
const app = initializeApp(firebaseConfig); db = getFirestore(app); auth = getAuth(); signInAnonymously(auth); onAuthStateChanged(auth, (loginUser) => { if (loginUser) { user = loginUser; } else { unsubscribe(); } });
Logged in page:
const app = initializeApp(firebaseConfig); db = getFirestore(app); auth = getAuth(); signInWithCustomToken(auth, customToken); onAuthStateChanged(auth, (loginUser) => { if (loginUser) { user = loginUser; } else { unsubscribe(); } });
Advertisement
Answer
I figured it out. I connect to the same firebase app from two places. First one from a Web Worker, with custom token auth, second one from a different tab from the same browser with anonymous sign in. When the second connection try to initiate a connection with anonymous auth, it doesn’t work because the app is already initiated with custom tokens, which fails this part of the rule,
request.auth.uid == docid
request.auth.uid is of the one who’s logged in.
Fix:
I had to create another app and a set of configurations to be used for logged in users. and then, I had to give an app name when I initialising and authorising the app.
const app = initializeApp(firebaseConfig, 'new-app'); db = getFirestore(app); auth = getAuth(app); signInWithCustomToken(auth, customToken); onAuthStateChanged(auth, (loginUser) => { if (loginUser) { user = loginUser; } else { unsubscribe(); } });