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();
}
});
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();
}
});