hide firebase private credentials in client apps - firebase

I would like to avoid exposing private credentials in client apps. Doug Stevenson said firebase-authentication-vs-firebase-admin :
The reason why you can't use the Firebase Admin SDK in your app is
because you would have to ship private credentials with your app in
order for the SDK to operate
By saying Admin SDK did he mean when we use for example:
import * as admin from "firebase-admin";
And what about :
import firebase from "firebase/app";
firebase.database().ref ... ?
Is this snippet considered as admin SDK ? To configure firebase we would still need to ship private credential with our client app, which is a security hole. So should we consider NEVER use firebase.database() or firebase.firestore() in client apps and instead use a cloud function ?

If you ship your administrative credentials with your application, anyone can grab those credentials and start calling any API on your project in whatever way they see fit. You have no control whatsoever over this usage, as they'll have the administrative credentials.
For this reason you should indeed not use the Admin SDK in the app, but instead wrap the functionality you need in a custom API (such as in a Cloud Function), where you can ensure its usage is authorized.
This is different from the second snippet in your question, which uses the regular JavaScript SDKs from Firebase. These SDKs don't use administrative credentials to access the project, but instead use the configuration data that is explained here: Is it safe to expose Firebase apiKey to the public?
Access through this configuration data is guarded by the server-side security rules that you've configured for your project. So while the user can still copy the configuration data and call the API on their own, any access has to go through the security rules you configured. And in those security rules you then ensure they can only access data they're authorized to.
But since the Admin SDKs bypass the security rules by design, you won't have that option when you ship the administrative credentials in your app.

Related

How firebase Admin SDK differs from firebase console web page?

I'm developing an android app with firebase as a backend and I heard a word named Admin SDK. I had searched for it and found it is used to manage data.
But I have a doubt that firebase provides a console webpage (console.firebase.google.com) to manage data, but why there is a separate Admin SDK?
Can someOne please explain...
The firebase admin SDK provides a simple and easy way to modify firebase settings and data using API calls.
For example, you might ask: why should you even have a regular SDK to store data? After all, you can store and save data directly from the web interface. It is, however, simply not secure or practical to have users update their own data each time using the console.
Similarly, the admin SDK is just like the regular SDK but with administrator permissions. For example, it allows you to bypass the rules set up using your firestore rules. The Firebase admin SDK is meant to be used on your backend - so you know it is running trusted software. You know that it will act the way you expect it to, unlike code running client-side that can't be trusted.
For example, let's say that you want to be able to delete a user's post if certain conditions are met. The user will make the request to your server, and it will check if the conditions are met, and then delete the post using its admin privilages. Sure you could technically automate this using firestorm rules, but those can be quite cumbersome and might not work in more complicated examples.
You can also even use it to integrate with other applications like connecting your app to a moderation tool or a curse detector that can't or shouldn't run on the client's device.
Is your question is why does Admin SDK exists?
There are several administrative tasks such as deleting users, listing collections and many more which the client cannot and should not be able to do.
Firebase Admin SDK has admin access to your Firebase project's resources.
It does not obey any security rules and can read/write any of your database, storage bucket..
That is why you must use Admin SDK in a server (or cloud function only). Although I feel Firebase Admin SDK is more useful if you use your own servers and authentication method. If you are using a custom server then:
It can be used to generate custom token so you can authenticate users using your own method (maybe legacy auth system) but still use Firebase Authentication to handle the auth tokens thereafter.
If you use your own database (and not any from Firebase), the Admin SDK can verify the ID Token sent by client and get identity of that user. Thereafter it's could be a simple if-else statement for you to decide if the user has access to the request resource or not.

Accessing firestore from self-hosted server

I need to be able to access (read, write) firestore from my self-hosted server (not on gcloud).
I also need to reserve write permissions to the app hosted on my self-hosted server, and allow noone else to be able to write to the server, so the security rules for write applications are denied by default.
According to this document:
https://firebase.google.com/docs/firestore/client/libraries#server_client_libraries
using a service account should allow me to be able to access all firebase products, including firestore, without any restrictions.
But, as soon as I restrict the security rules, I am unable to write to firestore from my service, instantiated with service account credentials following the steps in this documentation:
https://firebase.google.com/docs/admin/setup#initialize-sdk
I get the following error:
PERMISSION_DENIED: Missing or insufficient permissions.
What do I have to do to allow my application to write to firestore from my own servers?
Update:
I am using java for my backend applications.
Servers (or cloud functions) are secure environment which can be accessed only by you and people you have authorized. You don't actually use the Firebase Client SDKs in a server. Instead you use the Firebase Admin SDK. It uses a service account and has privileged access to your Firebase Project.
What does privileged access mean?
The documentation has explained it all but long story short it has complete access like you to the project. It does not follow any security rules.
If you are implementing the Admin SDK which will deal with API requests coming from your clients then make sure you authenticate them. To do so you would ideally pass the Firebase ID Token from your frontend to the API and verify
it using the Admin SDK which returns a decoded token object containing UID, custom claims and some metadata about that user.
I'm not sure which language you use but here's a simple getting started for NodeJS:
// Install the Admin SDK
npm install firebase-admin
// index.js
const admin = require("firebase-admin")
const path = require("path");
admin.initializeApp({
credential: admin.credential.cert("path/to/key")),
databaseURL: "https://<project-id>.firebaseio.com/"
})
const firestore = admin.firestore()
const auth = admin.auth()
// firebase.firestore() and firebase.auth() in client SDKs
Rest of the syntax is mostly the same as Client SDK.
You can create a service account from the project settings.
The issue that I was facing has already been reported here:
https://github.com/googleapis/java-firestore/issues/431
The fix was an odd one, and cannot be explained without going deep into the SDK and how it works, which I did not have time to check:

Why can't we connect to firestore on node.js server using just public apiKey

In my React project, I am using firebase public apiKeys to access services like authentication and firestore. So it means we are not required to use admin-sdk.
Then why we need admin-sdk to leverage firebase services on server environments like node.js? Won't public apiKeys do just fine?
I mean client side is exposed to public while servers can be accessed by only the managers and developers of the organization.
Please explain me the reason for this.
Thank You!
The client-side SDK's can access resources like Firestore, Storage, etc, but the requests to these services need to pass the Security Rules.
The Admin SDK bypasses the security rules - and hence the Admin SDK needs to be run in a secure environment.
To answer your specific query though - you can use the Javascript Client SDK on a Node.js environment - but you have to keep in mind that the requests will be subject to the security rules you define for your Firebase resources. If you use the Admin SDK, your requests will bypass the security rules.

firestore security rules for server side requests

i'm flutter-fire user since last fall
Note: The server client libraries bypass all Cloud Firestore Security
Rules and instead authenticate through Google Application Default
Credentials. If you are using the server client libraries or the REST
or RPC APIs, make sure to set up Identity and Access Management (IAM)
for Cloud Firestore.
Comment above is from link by firebase team. It sounds like 'server client libraries' or apis in the comment mean the requests from outside of my mobile apps, and they gon bypassing cloud firestore security rules. But when i tried the same get request with Postman with just same request from the one in my app without permission, the response in Postman console was fine, which means that there came a permission denied error.
So, here comes my question. I hope to know what types of requests exactly are equivalent to these 'server client libraries' or 'the REST or RPC APIs' mentioned in the official reference that bypass all the security rules. Postman is exactly 'the REST', and firebase worked as i wanted(produced permission denial) perfectly in this case. So there must be some specific types that firebase team actually intended to refer to be careful of.
I understand that firebase-admin sdk is one of the possible server side libraries, but exactly the same permission or auth procedures should be required when we tried to access firebase admin sdk which can control firebase data above the security rules just like firebase team commented. So the question is focusing on possible attackers' solutions to maliciously manipulate our firebase without the proper security procedures.
Hope some firebase gurus would give cool answers for the question with awesome knowledge and experiences! Thank you in advance [:
As their name indicate, the server client libraries are to be used from a server or from a "trusted environment" like Cloud Functions.
When interacting from your server (or your trusted environment) with the Firebase server APIs you don't authenticate as you would authenticate from a client application. Instead of using user accounts created through the Firebase Authentication service (e.g. email/password account) your server should use Google service accounts. More details here in the Firebase doc.
Note that for Cloud Functions, you initialize the Admin SDK with no parameters. In this case, the SDK uses Google Application Default Credentials (exactly as indicated in the documentation excerpt you mentioned in your question).
So, when your server (or your Cloud Function) interacts with the Firebase server APIs, since it is authenticated with a service account, the requests bypass all Cloud Firestore Security Rules. In other words, if you want to implement some check to allow/forbid specific operations based on specific parameters/values, you have to implement them in your code.
For the REST API, it is the same. The REST API can be used from a client application (a web app, a Flutter app, ...) or from a server.
Depending if it is a client or a server, you should authenticate by using a Firebase Authentication ID token or a service account (together with Google Identity OAuth 2.0 token), as explained in detail in the documentation.
So, when you make a request to the API with Postman without permission, as you did, the API detects that there is no Google Identity OAuth 2.0 token or Firebase Authentication ID token associated with the request and then the Security Rules are enforced => you get a "permission denied error".
In conclusion, if you correctly define your Security Rules you should not encounter any problem with "attackers maliciously manipulating" your database.
Note however that Security Rules only based on auth != null may not be sufficient to protect your data, as explained in this answer.

Is there any better way to handle GCD credentials than using private key file?

I would like to use the google cloud datastore from Android, so I would not have to set up cloud endpoints et al. Trying the snapshot 1.0.0 libs, the only way to add credentials seems to be via a file name to the private key file. That does not sound right for Android, is there some better way, ideally with an Android example?
You should be able to use the AccountManager for identity management and authentication storage, see https://code.google.com/p/google-api-java-client/wiki/Android.
You should be able to use the Oauth2 flow to get the appropriate credentials, and just pass that in to the DatastoreOptions.
Note that the Cloud Datastore API does not support fine grain ACLs, so the user will have to be an admin of your Project in order to access the API.

Resources