Firebase security rules, How to authenticate client app, not the users? - firebase

As I understand firebase security rules are for authenticating different types of users and provide authorization based on that, but what if my application doesn't need users to register at all? What if I just need to authenticate the application, not the users? What I mean by that is, I need to assure that particular firebase products are only accessed through an given application.
What I currently do to achieve that is, just make the security rules public assuming that the specific firebase sdk does the authentication stuff, but when I do that, I get the weird warning from the firebase console that security rules shouldn't be public. What am I doing wrong?
Another question, shouldn't we authenticate any application trying to access the firebase products even before starting the user authentication?
I also would like to learn how this is done generally (best practices) when developing serverless applications with firebase/google cloud platform products.

Firebase security rules don't support authenticating apps, only users. Authentication of an app would be pretty easy to simulate by an attacker, as all you would need is the secret compiled into the app in order to fool the rule. Even if you obfuscate the secret data, it's still just public data, and someone will figure out how to use it.
Once you ship an app to the world, you should consider everything in it to be public information, no matter how hard you might think it would be to extract that information (it's not that hard, really).

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?

End user authentication in Google Cloud Storage

in the last few days I have looked into Google Cloud Storage Buckets. I would like to know how to authenticate and authorize users when accessing data, preferably without the use of a backend.
Context: I have an app with the following requirements: Authenticated end users should be able to upload data to a (or their) bucket, with the default read access being scope to the user. At any point, the owner of the bucket should allow the bucket contents to be available to the public (publish bucket contents, read only).
End users are currently being authenticated with JWTs on the browser.
I have looked at the different ways of controlling access to Storage Buckets.
To my understanding:
IAM is unsuitable as it is meant for Google Accounts and should be used within the company, not to authenticate end users (clients)
ACLs are seemingly not recommended and are described as a legacy way meant for interoperability with S3
Signed URLs are "ok" for uploads, but I would rather have an actually authenticated way of uploading.
What's totally unclear to me: what access control method can be used to authenticate my end users (pref. with JWTs) especially for reading data?
This seems like an issue everyone should face, but I can't seem to find good info? On a side note: I am aware that Firebase exists for this reason, I just want to know how to tackle this on GCP.
There is no other solution than signed URL and a backend (I know that breaks your requirement) that check the authentication and generate that signedURL (on only the relevant/authorized files)
When implementing this purely in GCP, you'll typically end up implementing your own auth solution for your clients, and then your own authorization model in your server-side code.
If you want to not implement this yourself, using Firebase for your Cloud Storage access would be the way to go. This implements client-side authentication and server-side security rules to control access.

Firestore Security Rules - Accept requests from a verified Android App added in the GCP API Restrictions [duplicate]

I think from searching the web this is not technically possible but I want to ask again in case I'm missing something.
I have an app that uses Firebase. Reading and writing is locked down through security rules for authorised users only but there's certain information I want unauthorised users to be able to access (so I don't have to put a login wall in front of them, influencing churn).
What I want to know is, is there any way of locking down this read access that only my app can call the DB? I know I can lock down domains to prevent someone writing localhost scrapers but what's to stop someone cloning and re-skinning an app and pointing it to the same back end? Is it possible to achieve this using your certificates fingerprint?
There is no way to limit access to your database to just your app. That just doesn't match with the cloud-based nature of the Firebase APIs. Anyone that knows the URL of your database can in in principle access it, and security rule are the way to ensure all access is authorized.
Note that security rules are not an all-or-nothing approach: you can require sign-in for some parts of your database, while leaving other parts publicly readable. But you can't make the publicly readable parts only be readable by your own app.
Some previous questions on the same topic:
how to make sure only my own website (clientside code) can talk to Firebase backend? (pretty much my go-to answer for this)
How to allow only my app to access firebase without a login?
Restrict Firebase database access to one Android app
How to allow only my app to access firebase without a login?
Update: since May 2021 you can actually restrict access to just users of your App by implementing Firebase App Check.
I have found a solution that maybe helps you or anyone that have a similar question. I answered it in this question:
Restricting Cloud Firestore to a specific domain

Securing Firebase Database without having Firebase Auth

I am learning Flutter by following Codelab Firebase Tutorial and developing test Android app almost similar to this. Users save their baby name and others vote their favorites which updates Votes count in database. Based on this, I have few questions related to Firebase Security.
App does not currently have any Firebase Authentication. Is it necessary to have Firebase Auth seeing users who will just vote does not need to have any kind of registration.
Can someone decompile my app and get google-services.json file? If yes, will that allow them to use this file in their app and mess my database?
How much secure is my app from non-users like I mentioned in above point if I do not include firebase auth and keep security rules to default (read, write all)?
Apologies, If I failed to convey my point properly as I am still in learning stages of App development.
You must be using Firebase Authentiction if you want per-user read/write restrictions. If you aren't using it, you can only restrict what anyone in the world can do with public access.
Yes, anyone can get the values from your google-services.json file. They are added to your app as string resources. No, it doesn't allow anyone to access everything. What you're asking here is very common, try doing some searches for that. For example this.
If you use security rules that allow all read and write access, anyone with an internet connection will be able to read and write your database. This is not really acceptable in most cases.

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