Setting HTTP referer restriction on Firebase API key does not make a difference

Viewed 588

I would like to set a restriction on my Firebase API such that it can only be used from a particular domain.

Indeed, I understand that Firestore data is still readable unless correct security rules are in place, but I seem to be managing to make use of the Firestore API and the restriction should prevent this, if I understand correctly.

So, I have set my Browser key restriction as below, I clicked the Save button and waited five minutes.

enter image description here

Then I wanted to test this restriction, so I opened Incognito dev console, copied the identical Firebase config as it is on my client-side, and called the Firestore API as below:

var script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'https://www.gstatic.com/firebasejs/7.14.1/firebase-app.js';
document.head.appendChild(script);

var script2 = document.createElement('script');
script2.type = 'text/javascript';
script2.src = 'https://www.gstatic.com/firebasejs/7.14.1/firebase-firestore.js';
document.head.appendChild(script2);

// Your web app's Firebase configuration
const firebaseConfig = {
    apiKey: "exactly_the_same",
    authDomain: "exactly_the_same",
    databaseURL: "exactly_the_same",
    projectId: "exactly_the_same",
    storageBucket: "exactly_the_same",
    messagingSenderId: "exactly_the_same",
    appId: "exactly_the_same"
};

// Initialize Firebase
firebase.initializeApp(firebaseConfig);
const db = firebase.firestore();

db.collection('events').get().then((snapshot) => {  
    snapshot.docs.forEach(doc => {      
        console.log(doc)
    })  
})

The response I got was this, and looking into these elements even further, they contain the Firestore data.

enter image description here

Therefore, this restriction did not work at all, so what am I doing wrong?

UPDATE

It turns out that the HTTP referrer restriction only worked for non-Firestore APIs. I am not sure why this is the case, so I welcome anyone's thoughts on this. @willnode was correct in stating that you need two URL domain listings (including one with the wildcard) for the entire domain to be whitelisted. I observed this to work when I tested it with the Auth API (using anonymous sign-in).

The question as to whether restricting the API key with the HTTP Referrer is secure enough is a matter for another question.

ANOTHER UPDATE

For some reason we had to wait a bit longer for the Firestore API to also work with the Referrer restriction. Now everything is working as it should.

2 Answers

It is not safe to only base on HTTP referrers as it can be spoofed. If someone can extract your Firebase config from your web app code, then spoofing the domain takes the least amount of work for them that’s why authentication is important to remove spam users. If the users are not verified, then just provide a minimum functionality of your app until they verify it’s them.

For restricting to same domain requests App Check is our preferred recommendation, which protects your back-end resources from abuse. App Check is an additional layer of security that protects access to your services by attesting that incoming traffic is coming from your app, and blocking traffic that doesn't have valid credentials. For web apps, App Check uses reCAPTCHA v3 to reduce the chances of abuse.

For more information about the App Check, you can also check this guide.

I'd still recommend that you implement Authentication and Firebase Security Rules. If you don't want to require that your users enter credentials, you can use Firebase Anonymous Authentication to generate a unique UID for them. You can then check for that UID in your security rules, and still ensure that each user/device only accesses the data they're authorized.

Reading from the official documentation, you need to at least provide two restrictions for allowing any URL in a single subdomain or naked domain (you only provide one in your screenshot). Here's the excerpt:

1. You must set at least two restrictions to allow an entire domain.

2. Set a restriction for the domain, without the trailing slash. For example:
   + https://www.example.com
   + http://sub.example.com
   + http://example.com
3. Set a second restriction for the domain that includes a wildcard for the path. For example:
   + https://www.example.com/*
   + http://sub.example.com/*
   + http://example.com/*

If your domain allows both HTTP and HTTPS you must add additional restrictions separately.
Related