store private api key in flutter - firebase

I am using firebase and my backend API to get data for my APP.
The api requires a GCP key from access. This key expires every 90 days. So, I cannot store the key in the client/phone.
Need some ideas of where can I store the key.. I tried Firebase remote config and it works but the Firebase documentation said that sensitive data should not be used .
Creating a backend service that return the keys will not be secure as anyone can call the service,,
Need some suggestion. Is Firestore/Realtime database an option. The app will only read the data. However when the data changes(new keys) the App should get the latest.
Thanks for any suggestion

While distributing a private API key to the app at runtime through a mechanism like Remote Config, or a cloud database, may reduce the risk of it being intercepted, it is not enough to deter a sufficiently motivated malicious user. That's why the Remote Config documentation recommends against it, and the same applies to other distribution mechanisms (such as the databases you mention).
If this is a private API key, you should not use it in client-side code, period. That's really the only solution. When you use it in client-side code, a malicious user may get access to it and then abuse the backend service that is protected by the private API key.
Private API keys should be kept private, and only be used in a trusted environment (such as your development machine, a server you control, or Cloud Functions). When you allow users of your app to make calls through that private environment (by defining your own API for them), you will have to secure that end point yourself to ensure only authorized users can access them.

Related

How does Firebase authenticate requests from my app?

Disclaimer: I am new to mobile app development and have little to no knowledge on authentication systems
Normally, when my mobile app makes https calls to my backend server, I know that I cannot trust that these calls to my server came from my app, as anyone can make https requests to my backend server. Even if I give the app a secret key, it is still possible for a hacker to obtain the key and include it in https requests. Therefore, I will not allow https requests to accomplish whatever it wants on the server; rather, I will limit the request to doing only what a user can normally do with their own data – delete their OWN posts, edit their OWN profile, and so on.
Does Firebase work the same way? I saw this StackOverflow thread regarding OAuth consumer secrets, and how they can be compromised and used to imitate a mobile app.
Is this also the case for Firebase?
Can a malicious user theoretically obtain whatever keys/secrets Firebase gave to my mobile app, and use that to emulate requests from my app to Firebase? For example, could they create new users and cause de-syncing issues with my own backend database?
If so, how can I prevent it?
Thanks.
Does Firebase work the same way?
Firebase works in whatever way you program it. Normally you do not put private keys in software that you distribute to end users. The recommended approach is documented very well - use Firebase Auth ID tokens to indicate who is making the call, and use code on your backend to figure out if they should be able to do the work they are requesting. This is what happens with direct database access from your app, but you have to write security rules to protect data according to your requirements.
If you are passing tokens yourself to your own backend, it is up to you to revoke any refresh tokens that you find to be compromised. You cannot fully stop hackers from compromising a system that stores user tokens on devices that you don't control. All you can do is make it hard for them to do so.
Can a malicious user theoretically obtain whatever keys/secrets Firebase gave to my mobile app
Yes, that's why you don't put secrets in code that you distribute to end users. The Firebase config that you're asked to add to your app is not considered private.
See also:
Is it safe to expose Firebase apiKey to the public?

Unrestricted Firebase key can be used for other paid Google APIs

Firebase docs suggest firebase auto-created keys should not be restricted and unlike other sercet keys can happily appear in website's source:
Unlike how API keys are typically used, API keys for Firebase services are not used to control access to backend resources; that can only be done with Firebase Security Rules. Usually, you need to fastidiously guard API keys (for example, by using a vault service or setting the keys as environment variables); however, API keys for Firebase services are ok to include in code or checked-in config files.
The API keys auto-created by Firebase, by default, have no restrictions.
Secure your database and Cloud Storage data by using Firebase Security Rules, not by restricting and/or obscuring your API keys.
However, it seems that when we include our firebase key in our source code, it can be used by a malicious attacker to call paid Google services, such as Custom Search APIs which costs $5/5000 queries, thus draining the Google console balance of a poor unsuspecting victim.
Also, it seems adding restrictions to Firebase keys is not working - either preventing the key from working or triggering a creation of a new auto-generated key instead (see here, here, here)
So should we somehow restrict the api-key,
hide the key from the website's source
or something else?
I wasn't able to find anything about he malicious attacks using an API Key auto generated and can be restricted without any problem. Most of the posts you commented on have responses on how to solve their problems with the restriction options. Also, google documentation does recommend some API Key restriction.
Also, you have the App check to limit access to the backend services in your Firebase project.
Here there is also an article about security of the API keys in firebase.
So, after testing around and looking through some pages I think it's pretty safe to let some of them unrestricted and another ones restricted depending on what they are accessing to and you shouldn't have any problem.

Google Cloud and Firebase Browser vs Server key

So I am fairly new to firebase and new to the more advanced concepts of gcloud and i'm setting up firebase with hosting and analytics and in the gcloud console it generated a Server key and a Browser key however they look like identical keys, both unrestricted, and when i copied the code for the fire base analytics google sent me an email warning me about the api key being public (public github repo) is it safe to publish the unrestricted browser key, if so why? If someone could explain how api keys work within google cloud that would be great.
The Google Cloud Platform has a number of API keys. These are generated for Android, iOS and web (Browser) applications and there is also a Server API key. Anyone with an API key can call the REST APIs on resources on the project it was generated for. This can incur major billing charges!
It is advisable to restrict API keys. Only give them access to the APIs they need to use. Android and iOS keys should be restricted to the applications the project support.
The browser key is the one to be careful with as the key is stored in a JavaScript object and easily obtainable. It should be restricted to the domain the web pages are served from. If email address and password authentication is enabled, an unrestricted API key can be used to create and modify users.
So no, it is not safe to publish an unrestricted browser API key.

disclosing firebase apiKey

Documentation of firebase https://firebase.google.com/docs/web/setup tell us we can safely expose firebase apiKey:
Note: The Firebase config object contains unique, but non-secret
identifiers for your Firebase project.
The tutorial explains how to obtain the apiKey and insert it into the HTML code of our web app. Everyone can read that key. I would understand this is only an identification key.
But recently I received this message from google:
We have detected a publicly accessible Google API key associated with
the following Google Cloud Platform project:
[...]
The key was found at the following URL:
[...]
We believe that you or your organization may have inadvertently
published the affected API key in public sources or on public websites
(for example, credentials mistakenly uploaded to a service such as
GitHub.)
Please note that as the project/account owner, you are responsible for
securing your keys. Therefore, we recommend that you take the
following steps to remedy this situation:
If this key is intended to be public (or if a publicly accessible
key isn’t preventable):
Log in to the Google Cloud Console and review the API and
billing activity on your account, ensuring the usage is in line with
what you expected.
Add API key restrictions to your API key, if applicable.
If this key was NOT meant to be public:
Regenerate the compromised API key: Search for Credentials in
the cloud console platform, Edit the leaked key, and use the
Regenerate Key button to rotate the key. For more details, review the
instructions on handling compromised GCP credentials.
Take immediate steps to ensure that your API key(s) are not embedded in public source code systems, stored in download
directories, or unintentionally shared in other ways.
Add API key restrictions to your API key, if applicable.
In general I would say that the two sources of information are in contrast each-other. Is it true that the apiKey is "non-secret"? Reading also the related question Is it safe to expose Firebase apiKey to the public? I'm not really sure. I understand that the apiKey is enough to access the whole database if rules allow to.
First question: I wonder if I can be assured that the apiKey only gives access to the database (which can be restricted by rules) or if it gives also access to other information about the project. What about storage? The user can read files? Can write them? The key is called "web API key" so I understand is a unique identifier of the project. Before receiving the message from google I have considered it more as an identifier than a key. Since every access to the project API is a potential cost for me, the owner of the project, I understand that a key is required for billing purposes.
Second question. Since I would like to have full control of what user can access in the database my application is presenting a REST api as an interface to the database (using functions). So the user is not supposed to directly access the database. I have the following rules
service cloud.firestore {
match /databases/{database}/documents {
match /global/public {
allow read;
}
}
}
The intention is that user can only read the documents prefixed with /global/public (currently empty). So I think the database is secured. Now I wonder if I really need to expose the apiKey... Is the apiKey required for user authentication? If so, can I ignore the message from google and leave the apiKey public?
​

Can somebody get Firebase credentials from my apk and use them?

Can somebody else get the Firebase credentials from my APK and use them? Is this prevented by adding the SHA-1 keys for Android?
If it is prevented, what do I need security rules for since only code from my app with my SHA-1 can manipulate database at all?
If it is not prevented, can somebody else use my Firebase database as long as his requests fit the security rules? (Write 2nd client, which actually cannot do bad things but should not be allowed at all.)
Im not sure how I should think about security rules:
A) Protecting data against access and manipulation from bad guys + B?
B) Just a set of rules to keep data in a certain state and prevent my software from doing invalid database request?
A Firebase Database can be accessed via the REST API, or any of the client libraries. The decision about whether a client can or can't do something is entirely based on the rules.
You can even just access the Database URL in a web browser and see a JSON response by putting .json on the end, e.g. https://[YOUR_PROJECT_ID].firebaseio.com/.json
So the answer is definitely B! The default rules in a new Firebase project are that read and write to the database require auth, but you can configure them to provide whatever levels of protection you need.
Take a look at the Database Rules quickstart to see what you can do!
We don't ship the Realtime Database secret (or any other "secret" material) in the json file that gets baked into your app. That file simply contains resource identifiers that allow us to know which resources (database, storage bucket, analytics, etc.) to properly authenticate to (we use Firebase Authentication for these purposes), and we handle server side authorization to ensure that users are properly logged in.
If you are authorizing your requests properly (using Firebase Realtime Database Rules, for instance), your data is secure!
I'd recommend watching The Key to Firebase Security, one of our I/O talks, which talks in greater detail about how this works.
firebaser here
Thanks to the new feature called Firebase App Check, it is now actually possible to limit calls to your Realtime Database to only those 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 Mike and Ian describe in their answers, so that you have another shield against abusive users that do use your app.

Resources