Integration guide · Firebase
How to block disposable emails in Firebase Auth
Firebase can run a function before it creates a user. Use it to reject throwaway and dead-domain emails, so fake accounts never land in your user list or your analytics.
By the Vetto team · Updated
Quick answer
Deploy a blocking function with beforeUserCreated. Read the address from event.data.email, ask a disposable-email check for a verdict, and throw an HttpsError when it says “block”. On a timeout, return and let the user in.
1. Write the function
Keep the key in a Firebase secret, never in code:
// functions/src/index.ts
import { beforeUserCreated, HttpsError } from 'firebase-functions/v2/identity';
import { defineSecret } from 'firebase-functions/params';
const VETTO_SECRET_KEY = defineSecret('VETTO_SECRET_KEY');
export const blockdisposable = beforeUserCreated({ secrets: [VETTO_SECRET_KEY] }, async (event) => {
const email = event.data?.email;
if (!email) return; // phone and other email-less signups
let verdict;
try {
const res = await fetch('https://usevetto.com/v1/check', {
method: 'POST',
headers: {
Authorization: `Bearer ${VETTO_SECRET_KEY.value()}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ email }),
signal: AbortSignal.timeout(3000), // Firebase allows 7 s in total
});
verdict = await res.json();
} catch {
return; // timeout or network error: fail open
}
if (verdict.verdict === 'block') {
throw new HttpsError('invalid-argument', verdict.message || 'Please use a real email address.');
}
});2. Set the secret and deploy
firebase functions:secrets:set VETTO_SECRET_KEY # paste the sk_... key
firebase deploy --only functions:blockdisposableThen sign up with a throwaway address like x7@mailinator.com: the signup should fail. Gmail, Outlook and privacy relays like Apple Hide My Email go through.
3. Show a clear message in your app
try {
await createUserWithEmailAndPassword(auth, email, password);
} catch (err) {
// Blocking-function errors reach the client wrapped as an internal error,
// so show your own friendly message here.
setError('Please sign up with a real, permanent email address.');
}What the check catches
- Throwaway inboxes (mailinator.com, yopmail.com and 9,000+ more) and domains on known throwaway mail servers.
- Dead domains with no mail server.
- Repeat signups from one Gmail inbox through dots, +tags or googlemail.com, returned as a repeat count.
- Privacy relays are allowed, because a real person reads them.
Related: Supabase · Auth.js / NextAuth · how to detect fake signups · audit your existing users.
Frequently asked questions
Can Firebase Auth block disposable emails?
Yes, with a blocking function. beforeUserCreated runs before Firebase saves the new user; throwing an HttpsError stops the signup. Blocking functions need Firebase Authentication with Identity Platform.
Does beforeUserCreated run for Google sign-in?
Yes. Blocking functions run for new users from the supported providers, including OAuth sign-in. Anonymous and custom-token sign-ins do not trigger them.
How long can a blocking function take?
Firebase gives it 7 seconds, cold start included. After that the signup fails, so the example gives the check 3 seconds and then lets the user in.
Why does my client show "internal" instead of my message?
Firebase wraps errors thrown by blocking functions and returns them to the client as an internal error. Catch it and show your own message.
Give your signup form sharp eyes.
Free on one site. One line of HTML. Remove it any time and your form works exactly as before.
Founding offer: Pro for life for $69 once, first 100 buyers, until Nov 27.