DEV Community

Pranav Karawale
Pranav Karawale

Posted on • Updated on • Originally published at obnerd.in

How to keep your Firebase project safe and secure from everyone

After doing a couple of open source Firebase projects (web apps, I mean), I feel like I'm experienced* enough to write this post. So if I say something wrong here, kindly let me know here.

Why is this necessary?

I have a secret here(not really, just some people don't know about it). Your Firebase config, which you might have been wondering where to hide, is publicly visible(if you use Firebase hosting). Don't believe me? Go to the index page any site which uses Firebase hosting, and just append "/__/firebase/init.js" (eg. someapp.web.app/__/firebase/init.js) ans visit it, and you'll remain surprised by the result. This is something which is not discovered by me, its actually written in the documentation.

Protecting your project

Firestore datastore and Firebase Storage

This is perhaps the most important part of your backend which possibly contains sensitive data, which must be protected and it might cause harm when in the hands of bad people. So how to protect these? Well, here are some steps:

"Start in production mode"

When setting up Firestore and storage, you might get asked whether to start the resource in production mode or test mode. So always choose "Production mode" / "Locked mode". The reason is that this mode introduces some security rules that will block access from every client. Don't fear though, we can still change them.

Configure security rules

Security rules are very great to have. Using these, you can decide who can have access to data and who cannot. These are written in .rules files and have a similar syntax to JavaScript which can be understood in the docs. Since we used production mode, you will see this particular rule in your security rules:

match /{document=**} {
    allow read, write: if false;
}
//Don't remove this rule, or else your project is gone
//and keep this rule at end (this comment is added by me)
Enter fullscreen mode Exit fullscreen mode

Which literally means that no client can access your database and storage, which is sometimes not needed. So we can introduce changes in how we store data.
If you've used Firebase, you know that for every user that signs up for your app, they are assigned a unique ID (or UID). We can store resources based on their UID, for example, in a todo app, one can store user's data in their database at path /todos/users-uid which makes sense. So in this, we can add a new rule:

match /todos/{uid=**} {
    allow read, write: if request.auth != null and request.auth.uid == uid;
}
Enter fullscreen mode Exit fullscreen mode

This means that if anyone accesses any path under todos collection, they should be authenticated to the app, and if they try to access a specific UID in the collection, the database will only allow access if they access data under their UID.
Do the same for Firebase storage as well.

Use seperate API keys if they are used only for one purpose

Suppose you are also developing a CLI for your app (which I am doing), you might need your API key for refreshig the user's JWT (which I am doing :) ). So just don't use the same Firebase config API key, create a new one which has only access to the things we need, in this case, we need access to the Token Service API. So you can move to the Google APIs dashboard, and then select your preferred project.

  1. When you're in the dashboard, go to the 'Credentials' section.


  2. Then in the top app bar, click the "Create Credentials" button. A drop down will appear. Select "API key"

  3. Then it will show a dialog like this:


  4. Then that key will appear in the "Keys" section. Then, in that list, find the API key we just created, and then click on the pencil icon.

  5. Scroll down and you'll find a section "API restrictions". Select the option "Restrict key".

  6. Then a dropdown will appear with text "Select APIs". Then select the services which you want the API key to be working with. I'll select the Token Service API here.


  7. Just hit the "Save" button.

Then in the keys' section, you'll find that the API key has a green check on it. It means that it is now secure and you'll bear less damage if it got leaked.

If you need to have your API keys in your repo

If your code is public, and you need your API keys for testing or just to keep everything modular and smooth, encrypt it and then save it. I also use a similar approach in my CLI app, beacuse I need it for CI. You can use any encryption method which uses public-private key pair and then store the encrypted file in your repo and then decrypt it whenever needed.

Respect Firebase server credentials

Now this is important. We've been talking about the general Firebase config which we add in our web apps, but now, I'm talking about server credentials, which are used by the Admin SDKs. These are allowed access everywhere; no one can deny them. So treat them with respect and keep them as a secret only, don't show them off or else you're done.

Ending thoughts

Good job if you've made it this far. Now you can just chill back and write some code for your project. Always tell me if you got stuck in any of the steps. Have a nice day :)

Top comments (14)

Collapse
 
patarapolw profile image
Pacharapol Withayasakpunt • Edited

Even if you don't use Firebase hosting, the config object is still there (in the frontend / client-side/ web browser), just obfuscated.

Collapse
 
retronav profile image
Pranav Karawale

Yes, and unfortunately developers add unnecessary abstractions to hide, which is sad. I hope this article will help them.

Collapse
 
sarveshtheabstractor profile image
Sarvesh Hiwase

I am currently using React and Firebase and deployed my app on Vercel there is no config object in the console or what'soever.

Collapse
 
retronav profile image
Pranav Karawale

Hi Sarvesh,
Are you using Next.js or some other framework for your app? It'll be helpful if you tell that.

Thread Thread
 
sarveshtheabstractor profile image
Sarvesh Hiwase

I am using create-react-app

Thread Thread
 
retronav profile image
Pranav Karawale

Hi Sarvesh,
You should try configuring your environment variables like mentioned in the docs (link)
You should also set those environment variables in Vercel (link)
After these steps and double-checking, it will work

Thread Thread
 
sarveshtheabstractor profile image
Sarvesh Hiwase

Really thanks bro

Thread Thread
 
retronav profile image
Pranav Karawale

You're welcome :)

Collapse
 
sarveshtheabstractor profile image
Sarvesh Hiwase

is using environment variables for firebase config sufficient for security purposes or do they get exposed anywhere?

Collapse
 
retronav profile image
Pranav Karawale

Hi Sarvesh,
Assuming you're using environment variables in CI jobs, it is perfectly abstracted from the public. You need not worry getting them leaked. Its perfectly fine to store it in environment variables.

Collapse
 
sarveshtheabstractor profile image
Sarvesh Hiwase

Thanks brother, now I will be exploring firebase security deep down

Collapse
 
kevinmmansour profile image
Kevin M. Mansour

Hello

I am working in HTML and Firebase Project

Is it good to add firebase config in index.html (as People can see it ) or add it in JS file

Thanks

Collapse
 
retronav profile image
Pranav Karawale

Hello Kevin!
Its okay to add it in the HTML files. But since you'll be having JS files, my opinion would be to add it in the JS files.
Enjoy!

Collapse
 
akp111 profile image
Ashis Kumar Pradhan

I am using the firebase config in an extension I am working on. I am not able to store in .env file. I am using the config to generate device ID. Do you think someone can Ddos the extension?