Skip to content

Firestore Auth does not work in Cordova #2586

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Pitouli opened this issue Jan 31, 2020 · 20 comments · Fixed by #2626
Closed

Firestore Auth does not work in Cordova #2586

Pitouli opened this issue Jan 31, 2020 · 20 comments · Fixed by #2626
Assignees

Comments

@Pitouli
Copy link

Pitouli commented Jan 31, 2020

  • Operating System version: iOS 13.3 (iPhone 7)
  • Firebase SDK version: 7.7.0
  • Firebase Product: firestore

I have packaged my PWA as a Cordova application (everything is "out of the box" with Framework7)

The Auth is working as planned ; login/password is working without any modification, idem for anonymous auth. My Google identification is not working, but I know why (https://firebase.google.com/docs/auth/web/cordova -> need an Apple dev account).

My issue is that once connected, the Firestore functionalities seem unable to reach the backend. So everything works fine, but in offline mode. And I receive in the console the following message :

Firestore (7.7.0): Could not reach Cloud Firestore backend. Backend didn't respond within 10 seconds...

Since authentication is successful, I am certain that there is no real network issue.

To be honest, I do not know if it is a bug, or if I should use the iOS SDK.

So before I try to rebuild a testable project I can share with you, can you please confirm that Firestore JS should be compatible with Cordova app?

Thanks

@rommelpe
Copy link

rommelpe commented Feb 3, 2020

Thanks for reporting, @Pitouli. It might be related to #1190. Have you checked if you have any anti-virus installed like Kaspersky? It'd be always great to have a working repro to debug it further.

@Pitouli
Copy link
Author

Pitouli commented Feb 3, 2020

Hi @rommelpe
It works fine on the web on my computer. And it works fine when used with Safari on iOS (I have another issue, but most probably unrelated).
The Cordova issue I described happens when the app is package with Cordova, on iOS. And I do not have any antivirus on my iPhone.
I’ll try to create a small app to help reproduce the problem.
You confirm that normally I should be able to use the JS Firestore SDK in à Cordova app?
Thanks

@schmidt-sebastian
Copy link
Contributor

@Pitouli Can you share debug logs? You can enable them via setLogLevel: https://firebase.google.com/docs/reference/js/firebase.firestore#set-log-level. This should allow us to get a look at the sequence of events that causes the network failure.

In general, most of the Cordova related networking issues we have observed were caused by third-party plugins or ServiceWorkers. If your networking issues persists, we may need a reproduction to see if there are any dependencies that interfere with the WebChannel stack.

@Pitouli
Copy link
Author

Pitouli commented Feb 3, 2020

@Pitouli
Copy link
Author

Pitouli commented Feb 3, 2020

A project I created for debugging another issue (#2581) can be used to reproduce the bug.

The github : https://github.com/Pitouli/debug-ios-vuexfire
The app on the web: https://debug-ios-vuexfire.firebaseapp.com/

When you open it, you have a list of "dates". If you click on "add message", it publish a new "date" to the collection, which should appears on all the open apps.

As you can see, it works well on the web (except the bug described in the issue #2581 ).
But if you compile it for cordova (I can help you if you need info on how to do it), then the messages are not received (considered offline after 10 seconds).

@schmidt-sebastian
Copy link
Contributor

@Pitouli Thank for for the repro. I will give this a spin tomorrow (Tuesday) Pacific time.

@schmidt-sebastian
Copy link
Contributor

I am able to reproduce this using your app in the iOS Simulator.

@schmidt-sebastian
Copy link
Contributor

@Pitouli I looked at this more. What I actually see is a behavior that is similar to what users have described that are sitting behind corporate proxies. Some proxies only seem to forward responses once the connection is closed explicitly by the backend.

Due to the way WebChannel works (which is our network stack for the JavaScript-based client) this introduces a latency of 60s per request. This is well above the 10s threshold at which we consider the client offline.

The WebChannel team is currently trying to figure out if they can detect these situations automatically. Until that is the case, you can opt into a fallback that addresses this issue. If you set experimental-force-long-polling to true you app starts working:

firestore.settings({experimentalForceLongPolling: true});

Thanks for the repro. This will likely help many other users.

@Pitouli
Copy link
Author

Pitouli commented Feb 5, 2020

Thanks for your help!

My iPhone is a corporate one, but I do not think it has a special proxy. And for sure, my iOS Simulator has no corporate configuration, and it runs on a personal mac mini which is connected on a personal internet connexion (and I have not installed any firewall/antivirus), so I do not understand why there would be proxy issues.

Nevertheless, I tried to add the setting, and it effectively solved the issue on my "repro app", but sadly it hasn't solved my issue on my real app which uses Firebase Auth.

Now, I receive another error when I try to get() or onSnapshot() data:
[Error] Uncaught Error in onSnapshot: – FirebaseError: [code=permission-denied]: Missing or insufficient permissions. FirebaseError: [code=permission-denied]: Missing or insufficient permissions. (fonction anonyme) (cordova.js:1540) r (app.24c647.js:2:807334) (fonction anonyme) (app.24c647.js:2:766104)

Full log: https://gist.github.com/Pitouli/868f9c2158889f68cb7b20970b6603a3

Note that even with the setting experimentalForceLongPolling, the app still works as expected when it is not in Cordova (no "permission-denied" error).

I'll try to update my repro app to add an auth system, so I can request stuff controlled by firestore rules, and see if the issue can be reproduced.
Meanwhile, do you know if there is an "experimentalForceLongPolling" equivalent that I could use with Firebase Auth?

Thanks

Note: I cannot test on my iPhone until next week, so I only tested on the iOS Simulator

@schmidt-sebastian schmidt-sebastian changed the title Firestore + Cordova: Could not reach Cloud Firestore backend. Backend didn't respond within 10 seconds Firestore Auth does not work in Cordova Feb 6, 2020
@schmidt-sebastian
Copy link
Contributor

schmidt-sebastian commented Feb 6, 2020

My iPhone is a corporate one, but I do not think it has a special proxy. And for sure, my iOS Simulator has no corporate configuration, and it runs on a personal mac mini which is connected on a personal internet connexion (and I have not installed any firewall/antivirus), so I do not understand why there would be proxy issues.

I meant to say that Cordova exhibits the same network latency that we have seen on some corporate networks. For this, Cordova does not seem to have to be behind a Proxy.

Nevertheless, I tried to add the setting, and it effectively solved the issue on my "repro app", but sadly it hasn't solved my issue on my real app which uses Firebase Auth.

It looks like we need to add a special exception for Cordova to also omit some of our header values in our HTTP requests. You can see the code and the rationale for this:

@Pitouli
Copy link
Author

Pitouli commented Feb 7, 2020

Thank you for the details!
Feel free to ask if you need a small app to reproduce the bug, or if you you want me to test a new version of firestore to confirm the correction.

@schmidt-sebastian
Copy link
Contributor

@thebrianchen will be in contact should we need additional information.

@thebrianchen
Copy link

thebrianchen commented Feb 10, 2020

@Pitouli I am currently trying to reproduce the issue, and I am having trouble getting past the login screen. I've cloned your repo, and built the app with the command npm run build-prod-cordova-ios. From the /cordova directory, I am running cordova run iOS, which takes me to the app. However, I am stuck on the login screen and unable to proceed beyond it, as the login, sign-up, and google buttons don't seem to do anything.

What are the additional steps needed to get the app running? Also, where are the logs outputted to by default? Thanks!

@Pitouli
Copy link
Author

Pitouli commented Feb 11, 2020

@thebrianchen : I updated the app on the master branch to help you reproduce the bug I have on my "real" app.

Start by running the app as a web app: npm run dev

When the app opens in your browser, you should have a email/pwd form with a login and a sign-up buttons, and a "Google Connect" button below.
You can enter any email you want with any password you like and click "sign-up" to create (and automatically log in) an account.
If you want to log in an existing account, provide the correct email and corresponding password and click "login" instead (so you can be logged in the same account in your browser and in the cordova app for example).
Concerning the Google Sign-in, it works perfectly in the browser as expected, but requires special configuration to work with cordova, so simply ignore it (https://firebase.google.com/docs/auth/web/cordova -> need an Apple dev account).

Once you're logged in, you will see a home page.
On the top left, you have a burger button to reveal a panel where you can disconnect.
On the main page, you have 2 lists.
"Debug Firestore - Messages no auth": there is a button "Add Message" ; every time you click it, it adds a new message (a date) in a shared list (all apps are showing the same list).
"Debug Firestore - Messages auth": there is a button "Add User Message" ; every time you click it, it adds a new message (a date) in a list visible only for the authenticated user.
Note: everything else is part of the framework7 starter

Test in multiple browsers with multiple account: everything behaves as expected.

Now, compile the app for cordova and run it:
in the app folder: npm run build-prod-cordova-ios
in the cordova folder: cordova run ios

In cordova, everything works as described above, EXCEPT the "authenticated list": when you "Add User Message" in this list, you have an error in the console: Missing or insufficient permissions.

Three interesting things to notice:

  • the behavior is different for the web app (work as expected) and the cordova app (adding messages to the "auth" list does not work) -> the issue is specific to cordova
  • the "non auth" list continue to work perfectly, even in cordova -> the issue is not related to the fact that the user is authenticated
  • the "auth" list works in cordova if the firestore rules "allow everything"; it started to fail in cordova when I modified my rules so that only an authenticated user can write in its attributed collection -> the issue is related to the way cordova and the firestore rules interacts

Last but not least, these are my current rules (I commented below the "permissive rules" with which the auth list works correctly even with cordova):

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {

    // Make sure the uid of the requesting user matches name of the user
    // document. The wildcard expression {userId} makes the userId variable
    // available in rules.
    match /users/{userId} {
      allow read, update, delete: if request.auth.uid == userId;
      allow create: if request.auth.uid != null;
    }
    match /users/{userId}/{document=**} {
      allow create, read, update, delete: if request.auth.uid == userId;
    }
    match /messages/{message} {
    	allow read, write: if request.time < timestamp.date(2020, 4, 1);
    }

    // This rule allows anyone on the internet to view, edit, and delete
    // all data in your Firestore database. It is useful for getting
    // started, but it is configured to expire after 30 days because it
    // leaves your app open to attackers. At that time, all client
    // requests to your Firestore database will be denied.
    //
    // Make sure to write security rules for your app before that time, or else
    // your app will lose access to your Firestore database
    // match /{document=**} {
    //   allow read, write: if request.time < timestamp.date(2020, 3, 1);
    // }
  }
}

@Pitouli
Copy link
Author

Pitouli commented Feb 11, 2020

Also, where are the logs outputted to by default? Thanks!

Currently, I only tested the cordova app on iOS.

When you run a Cordova app on iOS (whether it is on a real device or on the simulator), you can access the console by using Safari on the mac connected to the iPhone / running the simulator.

Open Safari, choose "Development" in the menu bar (after having enabled development mode in the preferences of Safari) and you should find your (virtual) device in the list. And you should find the running app ready to be debugged.

@Pitouli
Copy link
Author

Pitouli commented Feb 11, 2020

Btw, I'm looking at my Firestore console and I observe that in one week there was 23k read of only 37 documents! 😢

Is it related to some tests you have run (in this case everything is fine; it's made for that)?
Or is it normal behavior with Firestore projects (which means that the 50k free read/days of my real app will quickly not be enough...)?
Or have I inserted an unwanted blackhole in my app that aspire all my data and probably my soul at the end (in this case I will look after an exorcist. Or learn how to code.)?
Or answer D?

image

@thebrianchen
Copy link

thebrianchen commented Feb 13, 2020

@Pitouli

Thanks for your detailed response on how to see the development logs for Cordova! I was able to reproduce the issue, and I've made changes that allow adding messages with auth in my reproduction. Can you verify that this custom version of firestore solves your problem (link)?

@thebrianchen
Copy link

Btw, I'm looking at my Firestore console and I observe that in one week there was 23k read of only 37 documents! 😢

It's hard to pinpoint exactly one reason for why your app has had so many reads just by looking at the table -- here are some common sources of usages:

  1. Firebase Console: Looking at the data in the Firestore console counts as read operations.
  2. Security Rules: Using get() and exists() in your security rules (which you don't seem to have).
  3. Failed Queries: Every read request has a minimum cost of one document per read, so even queries that return empty results or fail security rules will contribute to usage.

Lastly, you currently have your security rules set to public, so anyone can clone and access your database. If you tighten your security rules and continue to see high reads/writes, you should examine your app's Firestore API calls.

@Pitouli
Copy link
Author

Pitouli commented Feb 13, 2020

@thebrianchen

I do not know how to test your custom version 😅

I downloaded the archive, and I was hoping to replace the firebase folder in my node_modules folder by this one, but they do not seems to match at all.
I then thought that I could replace the content of the firestore folder (inside the firebase folder) by the content of your folder, but again, they seem very different from each other!


EDIT : I found the right folder, sorry!
(it is the firestore folder inside the @firebase folder and not inside the firebase folder)

@Pitouli
Copy link
Author

Pitouli commented Feb 13, 2020

Can you verify that this custom version of firestore solves your problem (link)?

Yes! It corrects the issue on my real app, at least with the simulator! I will test tomorrow (I need physical access to my computer) on my real device to be certain, but I am very confident it will work perfectly! 😃

Thanks a lot for your help, I'll keep you updated tomorrow about the success of the operation

@firebase firebase locked and limited conversation to collaborators Mar 15, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants