Firebase Email Enumeration Rules: A Workaround For fetchSignInMethodsForEmail
Chinomnso Awazie
Posted on February 4, 2024
If you manage users with Firebase Auth, this article will help you understand recent Google security implementation aimed at improving security of your users' identity information. You probably noticed that fetchSignInMethodsForEmail
started failing for new projects created after September 15, 2023. That is NOT a bug! Also, if you use Firebase Auth for users management, you probably got a nice email from Google letting you know that new projects from the date aforementioned now have e_mail enumeration protection enabled by default_. What does this mean? Why? What are the consequences to be expected? Speculations on possible direction Google is headed?
First, let us clarify a few things.
What is email enumeration?
Google Cloud documentation has a clean definition of this, so let me not reinvent the wheel here. In this article by Google Cloud, there is this concise definition of email enumeration:
Email enumeration is a type of brute-force attack in which a malicious actor attempts to guess or confirm users in a system by passing an email address to the API and checking the response.>
In the case of case of Firebase Auth, the attacker calls the Identity Platform API and tries to guess the existence or not of a particular user on the target project. There are a few ways this call can be made, eg via a REST API like createAuthUri, via a client SDK, etc. Basically, anyone who can access your https://www.googleapis.com/identitytoolkit
or https://cloud.google.com/gcp technically can enumerate users on the chosen project if they know their emails. A good Auth quota limit means emails obtained from a security breach, can be looped through to determine which emails are being used in that project. A more sinister case will be a bad actor, eg a scammer, a bad state actor, etc, who somehow gets access (eg API key, reverse-engineer an app to operated under the radar of that app's authentication, etc) being able to confirm the existence or otherwise of an account under the email of their victim. Zoom out a bit, and you realize how dangerous this is: in some places, belonging to an organization, group, using certain products or services, etc, can immediately spell grave threat to the life and safety of the individual if found by the government. I can already think of a few ways this would even get worse from there: confirm 'A' belongs to an organization, and then start fishing around 'A's circle to see who else is in that organization with them. I will not go further down that rabbit hole, but you get the point. And we are just painting the picture of one scenario!
There are quite a few ways to hit the EMAIL_NOT_FOUD
error on GCP, or its lil nephew auth/user-not-found
. What makes this a bit problematic is that you don't need a OAuth credential to get these responses, just the email, and an app with Firebase Auth properly initialized, or API key in the case of a REST API call.
What is the problem?
Abuse of a feature suggests the existence of a legitimate use. This also means that a lot of apps built their auth flow around this feature that enables them to first confirm the existence of an email on their platform, or lack of it. Typical scenario is most user onboarding process where you want to confirm there is no existing account with the email supplied by the new user trying to sign up, or you want to be sure someone trying to request a password reset even exists on your platform.
Now, here is the problem in my opinion: in a new user scenario, if that user comes in authenticated from a social auth provider, eg Google, Facebook, Apple, etc, trying to sign them in will create a new user in Firebase with their credentials! The cherry on top? The only method that has separate login and signup functions is the "email and password". Take a cursory look at the documentation around the methods available for Auth
service instance for an app. There is only but one "creatUser…" method, and that is createUserWithEmailAndPassword
. If you are coming from an auth provider, you just have to sign in, and if you do, and no user existed, a new one is created. Then there is the the isNewUser boolean that I have filed under "blink and you miss it": you get it only once. Interpretation: if for any reason a new user onboarding is incomplete, you will have to find other indirect ways to deduce they are new users on subsequent logins. Do you really want to expose too much user metadata to the FE in an attempt to maybe try figuring out the user age via their creation time? So how do we circumvent or at least mitigate email enumeration risks and still have a functionality that mimics fetchSignInMethodsForEmail? That is the point of this article.
My Solution
My suggested solution in one sentence: lean into Firebase Function. A function endpoint gives you some superpowers within your Firebase project, and you can still pile on other security measures. My go to defence mechanisms are:
- Enable AppCheck on your project and use it to protect your APIs.
- Implement strong encryption in transit. This is a good playground for security easter eggs: spice things up with encrypted stuff that should respond in a specific way in line with your business logic, a deviation of which will indicate malicious attempt.
- Use header information to filter for allowed origins at your API.
A sample code for the API could look like this:
The trick here is to use getUserByEmail method from the function API. This method is available with the elevated privileges of the admin . You can even mess with getUserByPhoneNumber if you so wish.
In my tests, with email enumeration turned on,fetchSignInMethodsForEmail fails at the client, but the API methods worked like charm.
If you liked this article, bookmark it for later, and share to help others.
Posted on February 4, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
February 4, 2024