I am a rather fresh Flutter programmer so please excuse any flaws in the questions below…
I am struggling with a structural/ architecture dilemma. Here is the background:
App rationale:
my app allows its users to check little jobs available in their area and if they find time and are in a proper location to execute the job for a remuneration,
the app uses standard REST API (not Firebase) so that the server cannot be relied on sending status change notifications to trigger re-fetching of data,
the critical elements are (1) up-to date list of jobs for a given address - other user may have already taken on a job in an address (timed refresh of list e.g. every 5 mins), and (2) the app needs to keep track of the user’s location and accordingly ask the server for jobs if the user relocates by more than 2km in less than the refresh time,
The challenge:
I guess that on the basic level the app should have the following providers: (1) auth – providing the authToken, (2) geolocation – regularly checking user’s location, (3) jobList - for particular location (fetches high level job descriptions and addresses(, (4) jobDetails – fetches exact instructions for carrying a particular job,
as you can see: (2) geolocation and (3) jobList – need to refresh programmatically (at interval or on some change of geolocation), while (1) auth, (4) jobDetails are triggered by the user.
The Big Question ;) is … what is the proper architecture for the above type of app? More specifically:
should I use services for connecting to the server API and these would in turn be used by the providers?
how to ensure programmatic refetch of jobList on timer and relocation event from geolocation?
how to continually listen to location changes to detect a relocation but not overwhelming the app with processing?
should I store the (quickly outdating) jobLIst data just in its object class or should I use settings provider or a local db or maybe there is an easy way of storing the latest JSON response not to have to build the settings provider or db mapping?
in all my call to Auth api I need to provide the deviceId - how to make it available accross the app - this is pretty static but is needed in authentication so should checking it be a part of the auth provider?
If you could comment on the above or suggest a source of relevant examples I would be really grateful.
Thanks and cheers!
Here are my thoughts:
how to continually listen to location changes to detect a relocation but not overwhelming the app with processing?
You can rely on third party to do this for you. Such as: geolocator. With this, you can specify the amount of distance the user must have moved before the package notifies you of the change in user location.
should I store the (quickly outdating) jobLIst data just in its object class or ...
Since it is likely for a job listing app to use this data often and in various places, I would prefer to use db. It would be helpful in the long run too, if you plan to have some sort of analytics done on the mobile end or to gather any insights.
in all my call to Auth api I need to provide the deviceId - how to make it available accross the app ...
When you app is initialized, you could fetch the deviceID and store it in shared_preferences. Then in auth api, you could just retrieve it before making the API call.
should I use services for connecting to the server API and these would in turn be used by the providers?
As for geo location, geolocator can update you about the change in location and you could make an API call based on that.
However, if you plan to have a timer based approach to refresh your job listing, then you must realize that your users are likely to face issues arising from your inconsistent data. If you have plans to tackle it, then this implementation here might help. But I strongly feel that server supporting push notifications or maybe a web socket approach would be ideal here.
Related
If I save API keys to Flutter_secure_storage, they must be exposed in the first place. How could they be pre-encrypted or saved to secure storage without exposing them initially?
I want to add a slight layer of security where keys are stored securely, only to be exposed when making an API call. But if I have keys hardcoded then they are exposed even if only at initial app run. How do you get around this logic?
To avoid exposing API key, you should store keys in a '.env' file and use flutter_dotenv package to access it while making API calls. Although this method will not help when making API call. If you really want to secure exposing keys, you should move the API calls to the backend so those network calls cannot be seen by the client.
If this is a web project, you could use something like base64 on both ends, then debase and save like this:
SERVER ON PHP
apiKeyEncoded = base64_encode(apiKeyGenerator());
CLIENT:
apiKeyEncoded = await getApiKey();
apiKeyDecoded = base64Decode(apiKeyEncoded).toString(); //this is the usable one, save it.
Now, if the project is focused on mobile use, I don't think you actually need to implement this, tho the code would be the same.
I will add some input to this. I am using Parse Back4App which exposes app API keys in the same way that firebase does. I have discovered a few very important security designs which may help with this.
Client side
Don't worry about app API keys being abused. Firebase/Back4App both have some security features in place for this including DoS & DDoS security features.
Move ALL actual API calls to server and call from client via cloud code. If you want to go to the extreme, create a user-device hash code for custom client rate limiting.
Server side
LOCK DOWN ALL CLPs, ALL ACLs, basically lock ALL PERMISSIONS and ONLY allow cloud calls with heavy security checks authorized access to anything server side including outside API calls.
Make API calls from your server only. Better yet, move your API calls outside cloud calls & create "cloudJobs", these run on schedule with Back4App and you can periodically call whatever API from server. Example: a crypto currency app might update prices once per second, once per minute etc. server gets these updates and pushes to clients. No risk of someone getting your crypto API keys and running the limits.
Put in a custom rate-limiting design & design around this so your rate limits would never trip under normal circumstances. If they do trip in excess, ban user & drop their requests.
Also put API keys in .env file on server. Go a step further & use a key encryption hardware service.
It would be a tell-tale sign that your server is compromised if your API keys get abused with this structure.
Want further DoS & DDoS protection? Mirror your server a few times and create a structure whereby client requests can be redirected under attack times or non-DDos/DoS attacking clients receive new app API keys.
... I could go on and on about security & what I've learned but I'll leave it at that.
my APP Is Really Depends on push Notifications, for examples iF the app has two actors, owner, and user, if the owner posts something, the user must be notified, based on their locations and Engagement in the app, which means the System first searches the nearest user and notify him, Notification is performed based on the location of the user, the user who is found in the nearest location is notified first, so What I want to ask you is, is it possible to achieve this without using firebase Cloud functions, Since firebase Cloud functions are NOT Free at this time. it asks me Billing account but the payment method is not available in my country
Apologies for my previous reply, I misunderstood the situation,
Also another solution besides one signal, you can use FCM on your own server, via FirebaseAdmin SDK. If you have a NodeJS server, a simple one, you can perform all firebase functions on it. In the end, it's not an absolute necessity to use cloud functions, it's just more convenient for a simple task or a few functions than spinning up your own server just for notifications. I would advise to go with this solution, and you will have access to cloud firestore via the admin SDK, you'll feel right at home.
Firebase cloud functions requires billing info, but you aren't charged. You have 2 MILLION free api calls per month. Then every extra 1 million calls cost less than half a dollar.
Do you know what 2 Million API invocations per month means? That's 32 THOUSAND API calls per day. If your app is generating that much traffic, trust me, you will not be worrying about these costs.
You can use OneSignal if you want, but it's more work for you, and it's outside the Firebase ecosystem.
Go with cloud functions, when you are reaching the limit of the free tier of 2Million monthly API requests, you can start looking for investors in your app.
I have some concerns about using Firestore directly from mobile clients. I saw that with Firestore, mobile app is controls to db directly. There is only db side control is rules. However I am not yet understand how can I resolve my concerns. I worrying because with decompiling app or any other ways maybe someone can access maliciously.
To resolve my concerns and improve the security I want to:
Limit access per time for user. For example if some one writes or
reads db 30 second ago I want to block their access until 1 minute.
Especially it is important for writing.
I want to have the only document owner write their documents and
block others to write. For do this I don't want to store owner id in
same document because if I put this information to there, readers can
receive this information and maybe some way they can write request
with this information.
In summary, I want to prevent malicious and excessive requests exceeding limits. I want to avoid the risks in db side. How can I resolve my concerns in the two above matter?
Scenerio:
Think that there is harmful someone with name X. X knows how to
decompile mobile app or maybe knows how to request my application's
firebase Firestore account (maybe watched communication I don't know).
X wants to harm my application. First X watching communication and if
we give owner userid in document X receives needed information so
sending request with changing his/her userid or auth.uuid. Secondly X wants to
disable firebase of my application. For do this X sends too much
requests. The limit is overs due to too many requests. Note that: I am
using Firestore directly with mobile application. There is no web
service to communicate.
How can avoid this scenario?
a question about local and remote storage of user data. Is there a best practices for the common situation where a user accesses data from an API and can favourite or otherwise personalise the data.
I have seen tutorials, e.g. a movie browsing app, where the use can make a list of favourite movies, where this personalised data is stored locally (e.g. in sqflite) and other tutorials where this data is stored remotely, eg. firebase. And firebase has an offline mode, so that data can be synced later. In that case, is it a common use case to set up local storage as well as cloud storage? Is there a common practice for this situation?
Thanks for any insights.
This is not specifically a Flutter question, more of a general app development question. It's very common to have both local and cloud "storage" but I wouldn't think of it that way. If you're interacting with an API backend I wouldn't consider it as the cloud storage for your app. Instead look at it as a different component within your applications overall architecture. You API/Backend component, this way it's not apart of your app instead it's something your app interacts with.
I assume you know the purpose of your API. Returns your data you want to see, keeps track of user profile information and other sensitive information.
When it comes to local storage I'd say the most common scenarios for local storage is results caching and storing information that the API requires on every session to make the user experience a bit better. See some examples below for both:
On instagram they store your "Feed watermark" which is a string value that is linked to a specific set of results so that when you open the app and request again they return that set of results, plus anything new - Local storage
They also "store locally" (better referred to as caching) a small set of your feeds from your posts, a list of user profiles that has stories on them and your DM's for instant and offline access. This way when the app loads up it has something to show while performing the action to get the new information. - Caching
They also store your login token, that never expires. - Local storage
tl;dr: Yes. If you need data on every session to use your API store that locally in a secure way and use that to interact with your "Cloud storage".
I would like to have my iOS application to check whether or not its server requests are going through, in order to register the number of users in a database based on which version of the API they're using.
I would then use these statistics to choose an appropriate time to roll out later versions of the application, and notify the users of the new release.
Would it be possible to get an example of the code required to perform these kinds of analytics?