801

The Firebase Web-App guide states I should put the given apiKey in my Html to initialize Firebase:

// TODO: Replace with your project's customized code snippet
<script src="https://www.gstatic.com/firebasejs/3.0.2/firebase.js"></script>
<script>
  // Initialize Firebase
  var config = {
    apiKey: '<your-api-key>',
    authDomain: '<your-auth-domain>',
    databaseURL: '<your-database-url>',
    storageBucket: '<your-storage-bucket>'
  };
  firebase.initializeApp(config);
</script>

By doing so, the apiKey is exposed to every visitor.

What is the purpose of that key and is it really meant to be public?

hc_dev
  • 8,389
  • 1
  • 26
  • 38
farmio
  • 8,883
  • 3
  • 13
  • 17
  • 1
    User Christophe Quintard had added a link to a very useful article with additional information regarding security of Firebase APIs, so I am reposting it here: javebratt.com/hide-firebase-api (The comment is going to disappear because it's attached to another user's answer which is flagged for deletion due to poor quality) – Oliver Schafeld Apr 27 '19 at 13:38
  • 13
    I just want to point out that just because this particular framework happens to be fine with exposing it's API, that doesn't mean that other frameworks are OK with it. Wouldn't want anybody to walk away from this post with the idea that "It's okay to expose API Keys" in general. – ICW Dec 21 '19 at 16:18
  • 4
    you expose keys with no problem. To make it safe, you can restrict it with specific domain in production so that no one else can make call API call from any random domain name. To make it more safe remove localhost from production app. – B L Λ C K Jan 20 '20 at 19:03
  • 6
    I don't think removing localhost from your referrers whitelist is going to do anything except make testing harder. That configuration isn't like an IP whitelist; think of it more like a CORS config. The way Firebase works is that those API routes are called directly from clients, they're not proxied. That's why your webpage needs the API key. If a bad actor wants to call your API routes from Postman, your referrer whitelist isn't going to stop them. It's only useful for preventing other public sites from mooching off your servers. – forresthopkinsa Apr 06 '20 at 09:00
  • 2
    If you want to stop an adversary from abusing your API by CURL then you need to implement other countermeasures like auth and rate limiting. This is an internet-facing API. That's a good thing!! Not a bug, a feature. – forresthopkinsa Apr 06 '20 at 09:03
  • The [Firebase docs](https://firebase.google.com/docs/projects/learn-more#config-files-objects) say `The content of the Firebase config file or object is considered public, including the app's platform-specific ID (Apple bundle ID or Android package name) and the Firebase project-specific values, like the API Key, project ID, Realtime Database URL, and Cloud Storage bucket name. Given this, use Firebase Security Rules to protect your data and files in Realtime Database, Cloud Firestore, and Cloud Storage.` – Vicktor Sep 22 '22 at 13:55
  • The [same docs](https://firebase.google.com/docs/projects/learn-more#config-files-objects) also say, `For open source projects, we generally do not recommend including the app's Firebase config file or object in source control because, in most cases, your users should create their own Firebase projects and point their apps to their own Firebase resources (via their own Firebase config file or object).` – Vicktor Sep 22 '22 at 14:04

10 Answers10

911

The apiKey in this configuration snippet just identifies your Firebase project on the Google servers. It is not a security risk for someone to know it. In fact, it is necessary for them to know it, in order for them to interact with your Firebase project. This same configuration data is also included in every iOS and Android app that uses Firebase as its backend.

In that sense it is very similar to the database URL that identifies the back-end database associated with your project in the same snippet: https://<app-id>.firebaseio.com. See this question on why this is not a security risk: How to restrict Firebase data modification?, including the use of Firebase's server side security rules to ensure only authorized users can access the backend services.

If you want to learn how to secure all data access to your Firebase backend services is authorized, read up on the documentation on Firebase security rules. These rules control access to file storage and database access, and are enforced on the Firebase servers. So no matter if it's your code, or somebody else's code that uses you configuration data, it can only do what the security rules allow it to do.

For another explanation of what Firebase uses these values for, and for which of them you can set quotas, see the Firebase documentation on using and managing API keys.


If you'd like to reduce the risk of committing this configuration data to version control, consider using the SDK auto-configuration of Firebase Hosting. While the keys will still end up in the browser in the same format, they won't be hard-coded into your code anymore with that.


Update (May 2021): Thanks to the new feature called Firebase App Check, it is now actually possible to limit access to the backend services in your Firebase project to only those coming from iOS, Android and Web apps that are registered in that specific project.

You'll typically want to combine this with the user authentication based security described above, so that you have another shield against abusive users that do use your app.

By combining App Check with security rules you have both broad protection against abuse, and fine gained control over what data each user can access, while still allowing direct access to the database from your client-side application code.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • 15
    So it means that other people would be able to access all the data in my firebase database? – Emmanuel Campos Jun 12 '16 at 14:30
  • See http://stackoverflow.com/questions/35418143/how-to-restrict-firebase-data-modification – Frank van Puffelen Jun 12 '16 at 15:31
  • 66
    @EmmanuelCampos Answer is Yes and No. Yes, if you allow or want the other people to access all the data in the database. And No, if you don't want them to. Firebase database has rules, rules that you control – KhoPhi Jun 12 '16 at 15:40
  • 3
    @Rexford How about user management? Wouldn't they just create a new app then they would use the auth of my app and they would be able to register their users in my users table? – Emmanuel Campos Jun 13 '16 at 00:15
  • 13
    Found my answer here for my last question https://support.google.com/firebase/answer/6400741 Thanks for the help. This link may help someone in the future. – Emmanuel Campos Jun 13 '16 at 03:40
  • How does it prevent on some user create a app based on my inicialization code? – m.rufca Oct 19 '16 at 18:27
  • 17
    @m.rufca , your data should be available for users, who are authenticated. And here is the trick. By default, in your firebase settings only localhost and your project domains are authorized to perform authentication from them. So nobody else can create app which will normally work with your firebase. – Artem Arkhipov Feb 13 '17 at 08:13
  • 4
    @Tamango This is good because prevent from user publish an app using my firebase service. But what if he runs on localhost? I'm asking this because I want to but my app code on github. – m.rufca Feb 13 '17 at 12:35
  • 2
    @m.rufca , I tried to find something about that and found logical answer from one of the firebase developers (posted on 16 december 2016): "It is not possible to disable localhost, but being able to run your code locally gives them no more permissions than running it from your production site. The user will only have access to their own /users/$uid node and will not be able to access any other user's data. There is no security issue here." Of course you are expected to configure firebase security rules before to allow users read/write only to their own parts of database. – Artem Arkhipov Feb 14 '17 at 15:46
  • 28
    what if bot is creating unlimited users at my app. How can I require captcha. – Muhammad Umer Mar 15 '17 at 02:45
  • 1
    This blog post also provides a nice explanation: https://javebratt.com/hide-firebase-api/ – prufrofro Feb 28 '18 at 00:18
  • 3
    @ArtemArkhipov what if a website get cloned and then get ran from localhost? Say someone copied the js code with the project ID, started the dev server on local host and ran it - would it also give him access to firebase (since the localhost is authorized to perform authenticaction) – Alexey Shevelyov Nov 15 '20 at 08:08
  • 3
    @AlexeyShevelyov I'm still new to Firebase myself but from what I've read is that even if someone clones your application perfectly and has the ability to connect to your Firebase it doesn't mean they're given access to your Firebase. A properly secured Firebase backend should require authentication before they can do anything and user credentials isn't something that inherently exists in the app itself. – Kevin Tian Jan 04 '21 at 04:44
130

Building on the answers of prufrofro and Frank van Puffelen here, I put together this setup that doesn't prevent scraping, but can make it slightly harder to use your API key.

Warning: To get your data, even with this method, one can for example simply open the JS console in Chrome and type:

firebase.database().ref("/get/all/the/data").once("value", function (data) {
    console.log(data.val());
});

Only the database security rules can protect your data.

Nevertheless, I restricted my production API key use to my domain name like this:

  1. https://console.developers.google.com/apis
  2. Select your Firebase project
  3. Credentials
  4. Under API keys, pick your Browser key. It should look like this: "Browser key (auto created by Google Service)"
  5. In "Accept requests from these HTTP referrers (web sites)", add the URL of your app (exemple: projectname.firebaseapp.com/* )

Now the app will only work on this specific domain name. So I created another API Key that will be private for localhost developement.

  1. Click Create credentials > API Key

By default, as mentioned by Emmanuel Campos, Firebase only whitelists localhost and your Firebase hosting domain.


In order to make sure I don't publish the wrong API key by mistake, I use one of the following methods to automatically use the more restricted one in production.

Setup for Create-React-App

In /env.development:

REACT_APP_API_KEY=###dev-key###

In /env.production:

REACT_APP_API_KEY=###public-key###

In /src/index.js

const firebaseConfig = {
  apiKey: process.env.REACT_APP_API_KEY,
  // ... 
};
now
  • 4,772
  • 2
  • 24
  • 26
  • 5
    Is that working fine for you? Was thinking to do the same thing for an Android app. I wonder why Firebase doesn't cover that in the security section. – steliosf Jun 28 '17 at 01:19
  • 3
    I've had no problem so far, but probably no attacks either – now Jun 28 '17 at 19:05
  • 5
    This is not mentioned in their guide because it won't protect you from scraping. All this ensures is someone else can not make a web app that uses your firebase to read (or write) data, if it's run in a normal well behaved browser. – thoutbeckers Jul 04 '17 at 11:56
  • 1
    In "Accept requests from these HTTP referrers (web sites)", add the URL of your app (exemple: projectname.firebaseapp.com/* ) This is not working. – Akash Arora Mar 08 '19 at 11:36
  • This still includes the exact same apiKey into the HTML/JavaScript that is served to the browser. The only difference is that the key is not included in the code you commit to the repository. If your goal is to prevent committing these keys to source control, this is a good approach. Is your goal is to protect from malicious users, this does not help in any way. – Frank van Puffelen Apr 12 '20 at 20:21
  • 2
    @FrankvanPuffelen From what I understand, it doesn't make a big difference, but can make it slightly more annoying to abuse your quota, since in a well-behaved browser, the API key served with HTML/JS will only work on the intended domain(s) and not localhost or anything else. But I agree that the added protection is marginal compared to what Firebase already provides. I'll reword the answer to something less dramatic. – now Apr 12 '20 at 21:06
  • If you put the `dev-key` in the source code (the file `env.development`). Anybody can find this key on the github repo, so it's not really safer. Wouldn't it be better to create two distincts firebase project, one for development purpose and one for production ? – Olivier Boissé Dec 28 '20 at 18:37
  • @OlivierBoissé For information you don't want to disclose, you can set up file like .env.development.local and not commit those. – now Dec 30 '20 at 20:57
  • 1
    Hi, I've followed your instructions but localhost still seems to be able to post. is there another setting that needs to be enabled? – Jaitsujin Aug 15 '21 at 23:22
  • @now how did you generate the public-key for production? i want to know the process because my Production Public Key is flagged during by our Penetration Tester as it is exposed in the code. – Compaq LE2202x Feb 11 '22 at 14:08
  • You public key is supposed to be public @CompaqLE2202x, it is expected and necessary to expose it in the client. It's similar to an API URL. – now Feb 12 '22 at 18:04
  • @now is your private key located safely in the backend server? – Compaq LE2202x Feb 14 '22 at 16:10
38

I am not convinced to expose security/config keys to client. I would not call it secure, not because some one can steal all private information from first day, because someone can make excessive request, and drain your quota and make you owe to Google a lot of money.

You need to think about many concepts from restricting people not to access where they are not supposed to be, DOS attacks etc.

I would more prefer the client first will hit to your web server, there you put what ever first hand firewall, captcha , cloudflare, custom security in between the client and server, or between server and firebase and you are good to go. At least you can first stop suspect activity before it reaches to firebase. You will have much more flexibility.

I only see one good usage scenario for using client based config for internal usages. For example, you have internal domain, and you are pretty sure outsiders cannot access there, so you can setup environment like browser -> firebase type.

Teoman shipahi
  • 47,454
  • 15
  • 134
  • 158
  • 16
    But isn't it the same as "exposing" any other REST API? I mean with REST API URL are available to user. They can use the URL to make any requests they want and drain your quota. What firebase do is using config with api keys to identify your part of backend and it is and it has to be available for user to make requests. – mbochynski Jun 05 '18 at 06:37
  • 7
    @mbochynski but you can somewhat make direct requests to resources that cause you pay bill. And at Firebase side there are not that much control mechanism to prevent DDoS attacks etc. My suggestion would be that let your client call your REST API, but that REST API should hold API Keys privately, and even before you hit Firebase resources, validate them if they are legit requests. (via Cloudflare etc). or retrieve results from cache. Then you will only hit your Firebase resources only if you will need to. This is what I would implement https://firebase.google.com/docs/admin/setup – Teoman shipahi Jun 05 '18 at 14:01
  • 8
    exposing keys at browser is seriously a bad idea. those to write all these guides/articles, what were they thinking? http referrer for security? that is easily spoofed – Nick Chan Abdullah Apr 10 '19 at 00:47
  • 7
    You guys aren't thinking about this right. Don't think of the API Key as a secret; it's not a private key, it's just an ID so the Firebase API knows who's accessing what project. If you want a lot of flexibility and you need to control every step of the server/client interaction then you shouldn't be using Firebase, you should be using GCP. – forresthopkinsa Apr 06 '20 at 08:54
  • @forresthopkinsa I have the link above comment what approach to take. No-one in here naive enough to suggest it is a secret key at all. – Teoman shipahi Apr 20 '20 at 03:42
  • These days with virtual CCs (X1, Citi, etc.) you can -- and _should_ -- set monthly spending limits for all SaaS. I set mine to $5 so that's the most I'll ever lose if someone abuses one of my API keys. – thdoan Jun 12 '23 at 08:53
11

The API key exposure creates a vulnerability when user/password sign up is enabled. There is an open API endpoint that takes the API key and allows anyone to create a new user account. They then can use this new account to log in to your Firebase Auth protected app or use the SDK to auth with user/pass and run queries.

I've reported this to Google but they say it's working as intended.

If you can't disable user/password accounts you should do the following: Create a cloud function to auto disable new users onCreate and create a new DB entry to manage their access.

Ex: MyUsers/{userId}/Access: 0

exports.addUser = functions.auth.user().onCreate(onAddUser);
exports.deleteUser = functions.auth.user().onDelete(onDeleteUser);

Update your rules to only allow reads for users with access > 1.

On the off chance the listener function doesn't disable the account fast enough then the read rules will prevent them from reading any data.

bzk
  • 306
  • 3
  • 6
10

I believe once database rules are written accurately, it will be enough to protect your data. Moreover, there are guidelines that one can follow to structure your database accordingly. For example, making a UID node under users, and putting all under information under it. After that, you will need to implement a simple database rule as below

  "rules": {
    "users": {
      "$uid": {
        ".read": "auth != null && auth.uid == $uid",
        ".write": "auth != null && auth.uid == $uid"
      }
    }
  }
}

No other user will be able to read other users' data, moreover, domain policy will restrict requests coming from other domains. One can read more about it on Firebase Security rules

8

While the original question was answered (that the api key can be exposed - the protection of the data must be set from the DB rulles), I was also looking for a solution to restrict the access to specific parts of the DB. So after reading this and some personal research about the possibilities, I came up with a slightly different approach to restrict data usage for unauthorised users:

I save my users in my DB too, under the same uid (and save the profile data in there). So i just set the db rules like this:

".read": "auth != null && root.child('/userdata/'+auth.uid+'/userRole').exists()",
".write": "auth != null && root.child('/userdata/'+auth.uid+'/userRole').exists()"

This way only a previous saved user can add new users in the DB so there is no way anyone without an account can do operations on DB.

Also adding new users is posible only if the user has a special role and edit only by admin or by that user itself (something like this):

"userdata": {
  "$userId": {
    ".write": "$userId === auth.uid || root.child('/userdata/'+auth.uid+'/userRole').val() === 'superadmin'",
   ...
Berci
  • 2,876
  • 1
  • 18
  • 28
7

EXPOSURE OF API KEYS ISN'T A SECURITY RISK BUT ANYONE CAN PUT YOUR CREDENTIALS ON THEIR SITE.

Open api keys leads to attacks that can use a lot resources at firebase that will definitely cost your hard money.

You can always restrict you firebase project keys to domains / IP's.

https://console.cloud.google.com/apis/credentials/key

select your project Id and key and restrict it to Your Android/iOs/web App.

JustRaman
  • 1,101
  • 9
  • 11
6

It is oky to include them, and special care is required only for Firebase ML or when using Firebase Authentication

API keys for Firebase are different from typical API keys: 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.

Although API keys for Firebase services are safe to include in code, there are a few specific cases when you should enforce limits for your API key; for example, if you're using Firebase ML or using Firebase Authentication with the email/password sign-in method. Learn more about these cases later on this page.

For more informations, check the offical docs

phoenixstudio
  • 1,776
  • 1
  • 14
  • 19
-3

I am making a blog website on github pages. I got an idea to embbed comments in the end of every blog page. I understand how firebase get and gives you data.

I have tested many times with project and even using console. I am totally disagree the saying vlit is vulnerable. Believe me there is no issue of showing your api key publically if you have followed privacy steps recommend by firebase. Go to https://console.developers.google.com/apis and perfrom a security steup.

-18

You should not expose this info. in public, specially api keys. It may lead to a privacy leak.

Before making the website public you should hide it. You can do it in 2 or more ways

  1. Complex coding/hiding
  2. Simply put firebase SDK codes at bottom of your website or app thus firebase automatically does all works. you don't need to put API keys anywhere
Aman Srivastava
  • 1,007
  • 1
  • 13
  • 25
user12449933
  • 170
  • 1
  • 6
  • 8
    I quote from Firebase, "Copy and paste these scripts into the bottom of your tag, but before you use any Firebase services," which includes the API key – Luke-zhang-04 May 31 '20 at 14:54