SaaS application using firestore's offline cache - firebase

I have created an ionic4 firestore mobile app. It's a SaaS application it has monthly subscription payments. My problem is how could I sell the app using firestore's offline capabilities? I mean making the app work offline adds value to my product but the users can use it for ever, with just offline caching. How can I stop users from using it after a month? Thank you.

If you wanted the opposite (allowing the user to continue using the app offline, but not online, after their subscription expires), you could do so by modeling this in the server-side security rules of your database.
But security rules are not applied while the client is offline. So there's no way to use security rules to reject users without a subscription.
This means you'll have to find a way to lock them out of your app itself, typically by storing (in the offline cache) until when their subscription is valid, and then refusing to start the app if that date is in the past.
A malicious user might be able to work around this, and access the data without your app. Since you're not paying for any database services at this point, that seems a decent trade-off. But if you don't think so, you can start looking at encrypting the data, which makes it harder for users to access the cache without your app. At this point you're pretty much in an arms race with malicious users though, so I'd seriously consider if the loss in potential revenue is worth the effort.

Related

Best strategy to develop back end of an app with large userbase, taking into account limitations of bandwidth, concurrent connections etc.?

I am developing an Android app which basically does this: On the landing(home) page it shows a couple of words. These words need to be updated on daily basis. Secondly, there is an 'experiences' tab in which a list of user experiences (around 500) shows up with their profile pic, description,etc.
This basic app is expected to get around 1 million users daily who will open the app daily at least once to see those couple of words. Many may occasionally open up the experiences section.
Thirdly, the app needs to have a push notification feature.
I am planning to purchase a managed wordpress hosting, set up a website, and add a post each day with those couple of words, use the JSON-API to extract those words and display them on app's home page. Similarly for the experiences, I will add each as a wordpress post and extract them from the Wordpress database. The reason I am choosing wordpress is that it has ready made interfaces for data entry which will save my time and effort.
But I am stuck on this: will the wordpress DB be able to handle such large amount of queries ? With such a large userbase and spiky traffic, I suspect I might cross the max. concurrent connections limit.
What's the best strategy in my case ? Should I use WP, or use firebase or any other service ? I need to make sure the scheme is cost effective also.
My app is basically very similar to this one:
https://play.google.com/store/apps/details?id=com.ekaum.ekaum
For push notifications, I am planning to use third party services.
Kindly suggest the best strategy I should go with for designing the back end of this app.
Thanks to everyone out there in advance who are willing to help me in this.
I have never used Wordpress, so I don't know if or how it could handle that load.
You can still use WP for data entry, and write a scheduled function that would use WP's JSON API to copy that data into Firebase.
RTDB-vs-Firestore scalability states that RTDB can handle 200 thousand concurrent connections and Firestore 1 million concurrent connections.
However, if I get it right, your app doesn't need connections to be active (i.e. receive real-time updates). You can get your data once, then close the connection.
For RTDB, Enabling Offline Capabilities on Android states that
On Android, Firebase automatically manages connection state to reduce bandwidth and battery usage. When a client has no active listeners, no pending write or onDisconnect operations, and is not explicitly disconnected by the goOffline method, Firebase closes the connection after 60 seconds of inactivity.
So the connection should close by itself after 1 minute, if you remove your listeners, or you can force close it earlier using goOffline.
For Firestore, I don't know if it happens automatically, but you can do it manually.
In Firebase Pricing you can see that 100K Firestore document reads is $0.06. 1M reads (for the two words) should cost $0.6 plus some network traffic. In RTDB, the cost has to do with data bulk, so it requires some calculations, but it shouldn't be much. I am not familiar with the pricing small details, so you should do some more research.
In the app you mentioned, the experiences don't seem to change very often. You might want to try to build your own caching manually, and add the required versioning info in the daily data.
Edit:
It would possibly be more efficient and less costly if you used Firebase Hosting, instead of RTDB/Firestore directly. See Serve dynamic content and host microservices with Cloud Functions and Manage cache behavior.
In short, you create a HTTP function that reads your database and returns the data you need. You configure hosting to call that function, and configure the cache such that subsequent requests are served the cached result via hosting (without extra function invocations).

How to secure database without authentication?

I am creating an Unity game where I want to have global top 50 score list with usernames. I use Firebase realtime database. There is no need for user to authenticate. I am not that familiar with database security and pretty beginner with this concept. I am using Rest Api from Unity Asset store because it was pretty easy to send and get data from databse.
How can I be sure that every score sent to database is from my app?
Add a dedicated user with password to your database
Somewhere in you app, add those credentials e.g. in a ScriptableObject / in some component
Always use those credentials to authenticate
Note that your app can still be decompiled and thereby cheated.
You can at least make it more difficult by encrypting the data etc.
The only way really around is to have an account and sessioning server to assure a user is locked in with a valid session.
If you don't use Firebase Authentication, you can't restrict who can access your database. Anyone will be able to issues a query, and they can even do it using the Realtime Database REST API. All they have to know is the name of your project.
Even if you do use Firebase Authentication, anyone may still effectively authenticate and access the database outside of your app using other public APIs.
My experience is that you can't stop dedicated "users" from cheating global at high scores. I made a small handfull of trivial games for windows phone with global top 50. Even if your game is unpopular, and you obfuscate your code, and you are on an unpopular platform, and you encrypt your network traffic: somebody is going to jailbreak their phone, decompile your app, and inject their own high score into your game before high scores are sent to the global list. The only way I ever came up with to combat this was to keep track of play sessions -on the server- to make sure their scores were theoretically possible based on how long they were playing.
Disclaimer: I don't know anything about Firebase
From what I can tell, you will need to set up access for Default and Public sections of your configuration to tell the database who can and cannot access your database. Here's their documentation on Get Started with Database Rules.
In general database access, no one should know the details of your connection to a database, so all calls should only ever come from your app.

Firebase Ecosystem - Security and Cost

In the Firebase ecosystem, for example in Cloud-Firestore, financial cost is highly dependent on factors such as document reads.
Is there anything protecting us from hostiles sending large numbers of read requests directly to our Firestore (circumventing our app) in order to drive our cost up?
Does the Firebase platform somehow recognise this and filter it out, or would we simply have to pay if this happened to us?
Clarification: Let's assume our Firestore security rules are such, that there are certain read requests which can be performed by anyone (allow read;). Consider for example a HackerNews type application, where anyone can list posts (no authentication required).
Cloud Firestore is designed to enable you to scale without experiencing an outage due to overload. We do enable you to set daily spending caps using the App Engine daily spending limit which can help prevent unexpected runaway costs.
There are a few other strategies to help control for this as well, such as using Firebase Auth and requiring users to sign-in, or doing server-side rendering of read-only results.

Understanding the Firebase and purpose of google cloud functions

Let's say I'm developing app like Instagram: for iOS, Android and Web. I decided to use Google Firebase as it really seems to simplify the work.
The features user needs in the app are:
Authorization/Registration
Uploading photos
Searching for other people, following them and see their photos
I come from traditional "own-backend" development where I do need to setup a server, create database and finally write the API to let the frontend retrieve the data from the server. That's the reason why it's unclear to me how it all works in Firebase.
So the question is how can I create such app:
Should I create my own API with cloud functions? Or it's ok to work with the database directly from the client-side?
If I work with the database directly why do I need cloud functions? Should I use them?
Sorry for such silly questions, but it is really hard to get from scratch.
The main difference between Firebase and the traditional setup you describe is that with Firebase, as far as the app developer is concerned, the client has direct access to the database, without the need for an intermediate custom API layer. Firebase provides SDKs in various languages that you would typically use to fetch the data you need / commit data updates.
You also have admin SDKs that you can use server-side, but these are meant for you to run some custom business logic - such as analytics, caching in an external service, for exemple - not for you to implement a data fetching API layer.
This has 2 important consequences:
You must define security rules to control who is allowed to read/write at what paths in your database. These security rules are defined at the project level, and rely on the authenticated user (using Firebase Authentication). Typically, if you store the user profile at the path users/$userId, you would define a rule saying that this node can be written to only if the authenticated user has an id of $userId.
You must structure your data in a way that makes it easily readable - without the need for complex database operations such as JOINs that are not supported by Firebase (you do have some limited querying options tough).
These 2 points allow you to skip the 2 main roles of traditional APIs: validating access and fetching/formatting the data.
Cloud functions allow you to react to data changes. Let's say everytime a new user is created, you want to send him a Welcome email: you could define a cloud function sending this email everytime a new node is appended to the users path. They allow you to run the code you would typically run server-side when writes happen, so they can have a very broad range of use-cases: side-effects (such as sending an email), caching data in an external service, caching data within Firebase for easier reads, analytics, etc..
You don't really need a server, you can access the database directly from the client, as long as your users are authenticated and you have defined reasonable security rules on Firebase.
In your use case you could, for example, use cloud functions to create a thumbnail when someone uploads a photo (Firebase Cloud Functions has ImageMagick included for that), or to denormalize your data so your application is faster, or to generate logs. So, basically you can use them whenever you need to do some server side processing when something changes on your database or storage. But I find cloud functions hard to develop and debug, and there are alternatives such as creating a Node application that subscribes to real time changes in your data and processes it. The downside is that you need to host it outside Firebase.
My answer is definitely NOT complete or professional, but here are the reasons why I choose Cloud Functions
Performance
You mentioned that you're writing an instagram-like mobile device app, then I assume that people can comment on others' pictures, as well as view those comments. How would you like to download comments from database and display them on users' devices? I mean, there could be hundreds, maybe thousands of comments on 1 post, you'll need to paginate your results. Why not let the server do all the hard work, free up users' devices and wait for the results? This doesn't seem like a lot better, but let's face it, if your app is incredibly successful, you'll have millions of users, millions of comments that you need to deal with, server will do those hard jobs way better than a mobile phone.
Security
If your project is small, then it's true that you won't worry about performance, but what about security? If you do everything on client side, you're basically allowing every device to connect to your database, meaning that every device can read from/write into your database. Once a malicious user have found out your database url, all he has to do is to
firebase.database().ref(...).remove();
With 1 line of code, you'll lose all your data. Okay, if you say, then I'll just come up with some good security rules like the one below:
This means that for each post, only the owner of that post can make any changes to it or read from it, other people are forbidden to do anything. It's good, but not realistic. People are supposed to be able to comment on the post, that's modifying the post, this rule will not apply to the situation. But again, if you let everybody read/write, it's not safe again. Then, why not just make .read and .write false, like this:
It's 100% safe, because nobody can do anything about anything in your database. Then, you write an API to do all the operations to your database. API limits the operations that can be done to your database. And you have experience in writing APIs, I'm sure you can do something to make your API strong in terms of security, for example, if a user wants to delete a post that he created, in your deletePost API, you're supposed to authenticate the user first. This way, 'nobody' can cause any damage to your database.

Firebase refresh-token expiration

While testing the security of one of our product, a web application, using the REST API of Firebase we got surprised when we realised that refresh-tokens never expire in the V3 of the Firebase implementation, allowing any refresh-token to create new tokens forever.
While local-storage seem a reasonably safe solution today, we are concerned by the possibility that it could fail tomorrow, even for a short amount of time, and that we cannot stop someone from using any of these refresh-tokens.
Two factor authentication will help mitigate the issue, but the first step would become compromised nonetheless.
Is there a way to blacklist tokens, or similar behaviour, with Firebase, without handling all tokens exchange, such as minting, ourselves? We could not find such feature when going through the doc.
Any advice appreciated.
Authentication sessions don't expire with Firebase login. But the ID token will have to be refreshed hourly, to keep access to the services. If you disable an account, refreshing the token will fail and the account won't be able to access services anymore. There is no way to invalidate individual tokens.
Firebase recently implemented revokeRefreshTokens() inside the admin sdk. Although this will not let you kill an invalid JWT, it does allow you to prevent a refresh of the token (from my testing so far at least) and it allows cleaner control flow inside firebase database.
See Admin Manage Sessions For rough examples

Resources