admin管理员组

文章数量:1126062

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=".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?

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?

Share Improve this question edited Apr 12, 2021 at 19:35 hc_dev 9,3291 gold badge30 silver badges42 bronze badges asked May 27, 2016 at 11:30 farmiofarmio 9,5833 gold badges14 silver badges17 bronze badges 7
  • 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 Commented Apr 27, 2019 at 13:38
  • 19 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 Commented Dec 21, 2019 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 Commented Jan 20, 2020 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 Commented Apr 6, 2020 at 9: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 Commented Apr 6, 2020 at 9:03
 |  Show 2 more comments

10 Answers 10

Reset to default 990 Answer recommended by Google Cloud Collective

From the Firebase documentation on using and managing API keys:

Firebase-related APIs use API keys only to identify the Firebase project or app, not for authorization to call the API (like some other APIs allow).

So the apiKey in your configuration snippet just identifies your Firebase project on the Google servers, but does on its own not allow access to it yet. 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 a longer explanation of what Firebase uses this configuration data for, and for which of them you can set quotas, see the 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.

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,
  // ... 
};

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.

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.

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.

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

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'",
   ...

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

According to me: With the key anyone can access our Firebase project resources. With security rules, we can avoid unauthorized access only, but someone can use the key in their application and authorize themselves and write data to db.

To avoid this, we can put some restrictions on the key such that the key can be used from our application domain only.

  1. Go to Google cloud console.

  2. Select the project in which the key is used

  3. Click API & Services

  4. You will be moved to the dashboard page. On the sidebar click credentials

  5. We would be redirected to the credential page. Hover the : at the end of the Firebase key and select edit-key option.

  6. On the edit page you can restrict the usage of keys. In the below image, I have selected the website option.

  7. Now we can add a domain on which the API key can be used.

  8. Click save

Faced a similar issue with just the auth workflow. If you are creating user accounts in firebase from your front-end, I would ask you to reconsider that. If you don't have any backend code that runs as a pre-trigger to creating a firebase user which checks weather the user is coming from your app or not, you should switch to creating the user from your backend and disable all sign up/sign in methods from the admin console. Since, backend service account keys are different from the front-end, they won't be exposed and you can manage them through the credential manager you prefer (env variables etc). This is also very helpful if your primary database is not Firestore (which is the case for a lot of enterprise apps who make heavy use of SQL but need firebase for some real-time functionality) and you don't need explicit credentials from the user to directly sign in to firebase. In your backend, you can create a custom token by using

getAuth()
  .createCustomToken(uid)
  .then((customToken) => {
    // Send token back to client
  })
  .catch((error) => {
    console.log('Error creating custom token:', error);
  }); 

Then, this custom token can be passed to the client where the client can sign-in into the firstore using the webSDK by

firebase.auth().signInWithCustomToken(customToken)
  .then((userCredential) => {
    // Signed in
    var user = userCredential.user;
    // ...
  })
  .catch((error) => {
    var errorCode = error.code;
    var errorMessage = error.message;
    // ...
  });

You would still need very robust and thorough security rules so that the access is fine grained and for RBAC. But, for me the issue was using the webSDK config keys from the client, the user can create an account or sign-in into my firebase project. But, this way it is ensured that the user cannot create an account and sign in without going through your own backend.

本文标签: javascriptIs it safe to expose Firebase apiKey to the publicStack Overflow