Open Krucial92 opened 4 years ago
@Krucial92 Thanks for reporting the issue! I was able to reproduce the error with your repo, and I'll update this issue once I investigate.
@thebrianchen thanks for looking into this, it will be great if we can get a fix in.
@Krucial92
You're using Firebase Admin's session cookies, which are incompatible with Firestore, RTDB, etc. Whenever the Firestore instance is restarted, states are lost, and no user is logged in, which means that you'll need to re-auth again. According to the manage cookies documentation:
For security reasons, Firebase session cookies cannot be used with other Firebase services due to their custom validity period, which can be set to the maximum duration of 2 weeks. All applications using server side cookies are expected to enforce permissions checks after verifying these cookies server side.
verifySessionCookie
will return true until the underlying JWT expires or is revoked. In your use case, it makes more sense to use Firestore in the Admin SDK instead of trying to use the Firestore SDK directly.
@thebrianchen thank-you for the clarification, appreciate your time. This did indeed turn out to be the issue.
One thing I would like to clarify, is it valid to use the Client SDK on the backend with the Admin SDK (doing most of the work), for these specific methods which are not provided by the Admin SDK such as signInWithEmailAndPassword, verifyPasswordResetCode & confirmPasswordReset?
I just want to make sure I understand this correctly. Does this mean that you can't use realtime updates client side if you are using Firebase Admin's session cookies? No way to hack around it?
@NixBiks Someone with auth knowledge will have to give a more complete answer.
What I can tell you about real time updates is that the snapshot listener will stop when the auth token expires. At that point, the SDK will automatically reconnect with a fresh auth token and resume where it left off. The Firestore component relies on auth to provide the token. So long as auth can provide valid tokens, the real time updates will work.
At this point, someone with knowledge of auth will need to describe under what conditions auth can provide valid tokens, and for how long. If a hack is used, then the hack needs to be applied periodically so that there is always a valid token. Otherwise, realtime time update through the snapshot listener will cease to function at some point.
@NixBiks Someone with auth knowledge will have to give a more complete answer.
What I can tell you about real time updates is that the snapshot listener will stop when the auth token expires. At that point, the SDK will automatically reconnect with a fresh auth token and resume where it left off. The Firestore component relies on auth to provide the token. So long as auth can provide valid tokens, the real time updates will work.
At this point, someone with knowledge of auth will need to describe under what conditions auth can provide valid tokens, and for how long. If a hack is used, then the hack needs to be applied periodically so that there is always a valid token. Otherwise, realtime time update through the snapshot listener will cease to function at some point.
I went ahead and implemented server auth with cookie while also keeping auth state client side (ie. persisting when logging in / fetching the token). Then I implemented some additional logic to keep server and client auth state in sync.
Environment:
Issue:
I believe I have found a bug with firestore, and have finally found what causes the issue to occur. Essentially firestore incorrectly returns a "permission-denied" response despite security rules being correct and the session cookie being verified.
This happens only in development when the node instance restarts!
Whether or not the NodeJS server restarts, if verifySessionCookie() passes and the user is logged in there should be no issue fetching documents which require auth from firestore.
How to reproduce:
I have created a minimal repo which demonstrates this exact issue: https://github.com/Krucial92/firestore-bug-example
Please follow these steps to reproduce:
1) Clone the repo and install dependencies for both the client & server 2) Inside /server/src/private/firebase-cert.json add your private key 3) Update /server/.firebaserc with your project, also go into /server/src/firebase.js and fill out the TODOs 4) Add this basic security rule into firestore:
5) Go into ./client and run
npm start
, also go into ./server and runnpm start
6) Now in the browser click "Sign Up", this will take a second. 7) Click "Fetch current user", you will see in the network requests that this is successful and you can fetch the users name "Johnny" from firestore. 8) Now restart the NodeJS server (you can also write something and let it hot-reload) 9) Now in the browser again click "Fetch current user" and you will see the network request fails with permission-deniedOther info
I really hope that this can be fixed soon, as it causes a very confusing developer experience. This lead me to believe that there was something wrong with my application or security rules, but further investigation into the issue seems like it is a problem with firestore.
What is happening on the backend and why would this occur? Appreciate any help or pointers in regards to this issue.