Using Firestore with offline persistence - Desktop (web) - javascript

Offline persistence in Firestore enables the browser to store records that were not uploaded to the server (offline) even after the session was closed (Browser exit)
Please see: https://firebase.google.com/docs/firestore/manage-data/enable-offline
However, firestore does not offer any officially supported way to clear the Chace when a user logs out from his session. Please refer to: https://youtu.be/qGAIimfrBB4?t=257
Recently they released the function clearPersistence, but they clearly state that is not meant for security reasons and recommend to disable Persistence if security is an important factor for you. Please see: https://firebase.google.com/docs/reference/android/com/google/firebase/firestore/FirebaseFirestore#clearPersistence()
Note: clearPersistence() is primarily intended to help write reliable
tests that use Cloud Firestore. It uses an efficient mechanism for
dropping existing data but does not attempt to securely overwrite or
otherwise make cached data unrecoverable. For applications that are
sensitive to the disclosure of cached data in between user sessions,
we strongly recommend not enabling persistence at all.
I want to understand better what's the security hole with using "ClearPersistence" on logout of the user.
Anyone experienced with that? Any other working solution that enables you to remove all the Firestore cache after a logout?

There is no guarantee that your code will run in the browser (or any other client). For example: a malicious user can take the configuration data from your application, and call the API to get access to the same data in your project, but then store it wherever they want.
Another malicious user might prevent the app from clearing the local cache, or quickly copy the local cache file to another location to have a copy before it is cleared.
And these are just two if the simplest examples. The simple fact is that you should assume that any data that exists/persists on the client can be seen by any user who has access to that client.

Related

How to make website work in offline mode and save data

Creating a project with JS and .net. which needs to work even in offline mode.
As I can see service worker can be used to cache static assets and can work offline, but we
can't save data to Database. Please let me know if the service worker can save data also.
Is there any better approach to making the website work in offline mode and save data somewhere and pass it to the database when online? The saved data should not be cleared when the user closes the browser
In theory you can use a localstorage to permanently save data. I suggest that you do not save sensitive information within it or that could, in the wrong hands allow unwanted access to your services and create problems for you.
You can find information about how it works here. You will find simple examples for its full use.
https://it.javascript.info/localstorage
However, making an app work fully without an Internet connection can be complex and should be analyzed in each precise circumstance. Any change operations to the database could be parked in the localstorage and provide for a worker to make the calls when the network returns. It is not simple what you asked and I cannot help you further.
You also need to understand how to handle getting information from a Database if you have no connection. Some functionality will have to be suppressed while for "static" obtainments you might think about caching (as also said by you).
You can use localStorage to save data to the browser even when in offline mode.
See MDN reference

Saving Firebase RTDB bandwidth by performing initial sync from JSON file

Firebase Realtime Database offers powerful synchronisation across clients... But it does seem to have rather high bandwidth charges.
I was hence wondering if it is possible to perform an "initial sync" on clients, so to speak, where we load a reasonably recent version of the database from elsewhere (with lower bandwidth charges), and then have the Firebase SDK (flutter, web) sync from there instead of downloading all the required parts of the database. Maybe a "load from JSON" sort of function or similar.
Seeing as to how the Firebase SDKs do seem to store some state locally on clients (for offline operation) and sync up with Firebase once online again, I was wondering if it might be possible to:
set the local state to our "recent version" downloaded from another source, along with that version's timestamp
trick the client SDK into thinking that we are recovering from an "offline" state
then let the SDK communicate with the Firebase server to get changes since our last timestamp
Are there any approaches to achieve the effect of saving bandwidth through performing an initial sync from a cheaper source? Thanks in advance!
Unfortunately every get() and every realtime listener will load all data it needs from the database. I had the same idea when started working with the Firebase RTDB but unfortunately at this moment it's not possible.
The only way to reduce the bandwith is to read data in smaller chunkgs as possible.
You might want to take a look at AceBase, which is an open source alternative for the Firebase RTDB. It offers the same functionality, has powerful indexing and querying options, offline support, synchronization etc. Easy to setup and you can host it anywhere you want. You can even use it as a standalone realtime database in the browser, so you could also use it in combination with Firebase to perform custom synchronization between your front and backend db's. AceBase is free and its full source code is public.

Use Persist Session in Meteor

Recently, I am working with Meteor.js and the problem arise from my development is how to use persist session for Meteor.js.
I have worked with Meteor session and it removed when I am refresh the site. So I realized I need to do something for my session.
I have worked with google and all of them I found out about the persist session is using localStorage.
If I use localStorage, my session should not been working on IE because IE doesn't support localStorage.
Is there any suggestion for my problem?
Thanks for your kind attention.
You can use ground db which also allows you client side offline content and thus makes your session data persistent on your users devices. This comes in handy if you want to have your clients manage the persistence storage while still being able to manage complex sets of data caching.
If this does not suit your needs, you could create a collection that acts as your session. The advantage is here that persistence is kept beyond client influence on the server. The hurdle is, that you need to implement a steady session-get-set mechanism with lots of Method calls and data updates.
A schema for this session could be:
{
userId:String,
state:{
type:Object,
backbox:true,
}
}
The blackbox attribute allows you to bypass validation and make this collection very flexible for use as session storage. Disadvantage is that it can create a security flaw because the incoming data is not validated by collection2-core (if you use it). You have to validate your variables yourself then.
I would prefer #Jankapunkt's approach, but just to put it out there, there is this unsupported package that does the job of persisting session variables over browser refreshes.
Eg: Session.set(key, value)

Secure user authentication in offline web apps

This question has cropped up a few times in various guises, but I've not seen an answer that satisfies my requirement or fills me with much confidence. Let me set the scene.
We currently have a web application, which allows users to submit responses to pre-set questions where the data ends up in an SQL Server database, we also have a Windows application that does the same thing but works in an offline capacity; i.e. it connects to the SQL Server, downloads the questions, allows the user to complete them offline and when they next have a network connection they can synchronise the data, uploading it to the SQL Server. Great!
As part of our development strategy, given HTML 5's offline capabilities and local storage,it seems perfectly sensible to attempt to consolidate these products into a single web application. This would mean we're able to work on a single code base, and this would also enable the application to run in a browser on most devices; platform independent.
Looking into this I see a couple of potential problems, I'd really appreciate a steer on these:
Users need the ability to login, in offline and on-line modes. This could mean we download the hash's of the all users usernames and passwords, or just those that have logged in whilst in on-line mode. However, even doing this there needs to be a way to check these and given that the Javascript is readable someone could easily reverse engineer their credentials. Yes you can obfuscate the code but this isn't infallible.
The data that needs to be stored locally could be highly sensitive; contain personal information etc. Therefore this also needs encrypting, at minimum AES 256.
Am I hoping for utopia? Is this something that's just not possible at this time? Do I need to be looking at another solution and dismissing this for the time being?
Any help from you lovely people would be much appreciated.
First the easier question 2: that is perfectly possible. You can generate the key on the device and on sync send it via https to your server which can decrypt the data then.
As for question 1 I'd say an offline login is not really feasible BUT do you actually need one? Once the questionaire is downloaded (which requires online mode, so requiring login is fine) you only need to transmit it on sync, where online is again required and you can ask the user for his login there, too. I'd not recommend to download any sensible user data (e.g. hashes) to the device.
What you can do is to cache the current user only after logging in online. This would mitigate the risk of enumerating the users in your local DB.
You then need to encrypt the user's data on the front-end, I'd go with a library that does the job for you (for example, RxDB). RxDB accepts a password (which you can generate on the fly) and based on it, encrypts your DB data. The user then fills in the form (does whatever he wants) and if all of the sudden the internet is gone, the user is still able to continue his work and that work must be added as pending requests in order to do the sync. (which you already have)
When the internet is restored, you're going to check whether the session has expired for the user and if so, prompt the user to log in again and do the sync if it was the same user. If it's still there, perform the sync.
My advice based on my personal experience for the offline part.
You can create a local variable that allows the user to login once using internet for the first time then he will be able to auto login for several times as much as you decided in the local variable and when the value is 0 he will need an internet again to get another offline access for the same value you decided before.
so, in a small words. offline counter that will need an internet Only after many offline logins (when the counter decrease to 0)
Flowcharts

how to make sure only my own website (clientside code) can talk to Firebase backend?

I've read about Firebase and it looks awesome for what I want to do.
I've read about authentication and how based on rules certain logged-in users are authorized to do different stuff. Al good.
However, I'm unsure about another type of security: how do I make sure that only my own site (using client-side javascript) can talk to my firebase-backend? I'm asking because afaik there's no way to prevent anyone from looking up my firebase endpoint from the client-side code (url pointing to my specific firebase backend) and start using that for god knows what.
This is especially worrisome in situations in which I want to open up writes to the anonymous user role. (e.g: some analytics perhaps)
Any help in clearing my mind on this much appreciated.
Update (May 2021): Thanks to the new feature called Firebase App Check, it is now actually possible to limit calls to your backend service to only those requests coming from iOS, Android and Web apps that are registered in your Firebase project.
You'll typically want to combine this with the user authentication based security that Kato describes below, so that you have another shield against abusive users that do use your app.
In my opinion, this isn't so much a question about Firebase's security as a general discussion of the internet architecture as it stands today. Since the web is an open platform, you can't prevent anyone from visiting a URL (including to your Firebase) any more than you can prevent someone from driving past your house in the real world. If you could, a visitor could still lie about the site of origin and there is no way to stop this either.
Secure your data with authentication. Use the Authorized Domains in Forge to prevent CSRF. Put security rules in place to prevent users from doing things they should not. Most data writes you would use a server to prevent can be accomplished with security rules alone.
This is actually one of the finer qualities of Firebase and API services in general. The client is completely isolated and thus easily replaced or extended. As long as you can prove you're allowed in, and follow the rules, where you call in from is unimportant.
Regarding anonymous access, if you could make them visit only from your site, that still won't stop malicious writes (I can open my JavaScript debugger and write as many times as I want while sitting on your site). Instead, place tight security rules on the format, content, and length of data writable by anonymous users, or save yourself some time and find an existing service to handle your analytics for you, like the ubiquitous Google Analytics.
You can, of course, use a server as an intermediary as you would with any data store. This is useful for some advanced kinds of logic that can't be enforced by security rules or trusted to an authenticated user (like advanced game mechanics). But even if you hide Firebase (or any database or service) behind a server to prevent access, the server will still have an API and still face all the same challenges of identifying clients' origins, as long as it's on the web.
Another alternative to anonymous access is to use custom login, which would allow a server to create its own Firebase access tokens (a user wouldn't necessarily have to authenticate for this; the signing of the tokens is completely up to you). This is advantageous because, if the anonymous user misbehaves, the access token can then be revoked (by storing a value in Firebase which is used by the security rules to enforce access).
UPDATE
Firebase now has anonymous authentication built into simple login, no need to use custom login for common use cases here.

Categories