To enable email verification in Firebase, call sendEmailVerification() on the current user object immediately after signup. Check the user's emailVerified property before granting access to protected features. Configure actionCodeSettings to redirect users back to your app after clicking the verification link. Combine this with Firestore security rules that check request.auth.token.email_verified for server-side enforcement.
Setting Up Email Verification in Firebase Auth
Email verification confirms that a user owns the email address they signed up with. This tutorial covers sending the verification email, checking the verified status, customizing the email template redirect URL, and enforcing verification at both the client and security rules level. You will build a complete verification flow that prevents unverified users from accessing protected resources.
Prerequisites
- A Firebase project with Authentication enabled
- Email/Password sign-in provider enabled in the Firebase Console
- The firebase npm package installed (v9 or later)
- Basic knowledge of JavaScript/TypeScript
Step-by-step guide
Send a verification email after signup
Send a verification email after signup
After creating a new user with createUserWithEmailAndPassword, the returned UserCredential contains the user object. Call sendEmailVerification() on this user to trigger a verification email. Firebase sends the email automatically using its built-in email template. The email contains a link that, when clicked, sets the user's emailVerified property to true.
1import { getAuth, createUserWithEmailAndPassword, sendEmailVerification } from 'firebase/auth'23const auth = getAuth()45async function signUpWithVerification(email: string, password: string) {6 const userCredential = await createUserWithEmailAndPassword(auth, email, password)7 const user = userCredential.user89 await sendEmailVerification(user)10 console.log('Verification email sent to', email)1112 return user13}Expected result: A verification email arrives in the user's inbox with a link to confirm their email address.
Configure the verification redirect URL
Configure the verification redirect URL
By default, the verification link opens Firebase's default action handler. Use actionCodeSettings to redirect users back to your application after they verify their email. The url parameter is where users land after clicking the verification link. Add this URL to the Authorized Domains list in Firebase Console under Authentication > Settings.
1import { sendEmailVerification } from 'firebase/auth'23const actionCodeSettings = {4 url: 'https://your-app.com/verified',5 handleCodeInApp: false,6}78async function sendVerification(user: any) {9 await sendEmailVerification(user, actionCodeSettings)10}Expected result: After clicking the verification link, users are redirected to your specified URL instead of the default Firebase page.
Check email verification status on the client
Check email verification status on the client
After the user clicks the verification link, their emailVerified property updates to true. However, the local auth token may be stale. Call reload() on the user object to fetch the latest verification status from the server, then check emailVerified. Use this check to gate access to features that require a verified email.
1import { getAuth } from 'firebase/auth'23const auth = getAuth()45async function checkVerification() {6 const user = auth.currentUser7 if (!user) return false89 // Refresh the user's profile from the server10 await user.reload()1112 if (user.emailVerified) {13 console.log('Email is verified')14 return true15 } else {16 console.log('Email is not yet verified')17 return false18 }19}Expected result: The function returns true when the user has clicked the verification link, false otherwise.
Gate protected routes based on verification status
Gate protected routes based on verification status
Create a wrapper component or middleware that checks emailVerified and redirects unverified users to a prompt page. Listen for auth state changes with onAuthStateChanged, and after detecting a logged-in user, check their verification status. Show a prompt to resend the verification email if the user has not yet verified.
1import { useEffect, useState } from 'react'2import { getAuth, onAuthStateChanged, sendEmailVerification, User } from 'firebase/auth'34function useAuth() {5 const [user, setUser] = useState<User | null>(null)6 const [verified, setVerified] = useState(false)78 useEffect(() => {9 const auth = getAuth()10 const unsubscribe = onAuthStateChanged(auth, async (firebaseUser) => {11 if (firebaseUser) {12 await firebaseUser.reload()13 setUser(firebaseUser)14 setVerified(firebaseUser.emailVerified)15 } else {16 setUser(null)17 setVerified(false)18 }19 })20 return () => unsubscribe()21 }, [])2223 const resendVerification = async () => {24 if (user && !user.emailVerified) {25 await sendEmailVerification(user)26 }27 }2829 return { user, verified, resendVerification }30}Expected result: Unverified users see a verification prompt with a resend button; verified users access the protected content.
Enforce verification in Firestore security rules
Enforce verification in Firestore security rules
Client-side checks can be bypassed. Add server-side enforcement by checking email_verified in your Firestore security rules. The request.auth.token object contains email_verified as a boolean. This ensures that even if someone bypasses your UI, they cannot read or write protected data without a verified email.
1// firestore.rules2rules_version = '2';3service cloud.firestore {4 match /databases/{database}/documents {56 // Only verified users can read or write posts7 match /posts/{postId} {8 allow read, write: if request.auth != null9 && request.auth.token.email_verified == true;10 }1112 // Public data readable by anyone authenticated13 match /public/{docId} {14 allow read: if request.auth != null;15 }16 }17}Expected result: Unverified users receive 'Missing or insufficient permissions' when trying to access protected collections.
Complete working example
1import {2 getAuth,3 createUserWithEmailAndPassword,4 sendEmailVerification,5 onAuthStateChanged,6 User,7} from 'firebase/auth'89const auth = getAuth()1011const ACTION_CODE_SETTINGS = {12 url: 'https://your-app.com/verified',13 handleCodeInApp: false,14}1516export async function signUpAndVerify(17 email: string,18 password: string19): Promise<User> {20 const { user } = await createUserWithEmailAndPassword(auth, email, password)21 await sendEmailVerification(user, ACTION_CODE_SETTINGS)22 return user23}2425export async function resendVerificationEmail(): Promise<void> {26 const user = auth.currentUser27 if (!user) throw new Error('No user signed in')28 if (user.emailVerified) throw new Error('Email already verified')29 await sendEmailVerification(user, ACTION_CODE_SETTINGS)30}3132export async function isEmailVerified(): Promise<boolean> {33 const user = auth.currentUser34 if (!user) return false35 await user.reload()36 return user.emailVerified37}3839export function onVerificationChange(40 callback: (verified: boolean) => void41): () => void {42 return onAuthStateChanged(auth, async (user) => {43 if (user) {44 await user.reload()45 callback(user.emailVerified)46 } else {47 callback(false)48 }49 })50}Common mistakes when enabling Email Verification in Firebase Auth
Why it's a problem: Checking emailVerified without calling user.reload() first, seeing stale unverified status
How to avoid: Always call await user.reload() before reading emailVerified. The local auth token caches the old value until refreshed.
Why it's a problem: Not adding the redirect URL to Firebase's Authorized Domains list, causing the verification link to fail
How to avoid: Go to Firebase Console > Authentication > Settings > Authorized Domains and add your app's domain. Without this, Firebase rejects the redirect URL.
Why it's a problem: Only enforcing email verification on the client side, allowing API-level bypasses
How to avoid: Add request.auth.token.email_verified == true to your Firestore security rules for any collection that requires verified users.
Best practices
- Send the verification email immediately after signup so users can verify while completing onboarding
- Always call user.reload() before checking emailVerified to get the latest status from the server
- Add a resend button with a cooldown timer to handle users who did not receive the first email
- Enforce email verification in Firestore security rules, not just on the client side
- Customize the actionCodeSettings redirect URL to bring users back to your app after verifying
- Inform users to check their spam/junk folder if the verification email does not arrive
- Use Firebase's email template customization in the Console to match your brand
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I want to add email verification to my Firebase Auth signup flow. After a user signs up with email and password, send a verification email, redirect them back to my app after clicking the link, and block access to certain Firestore collections until verified. Show me the complete code.
Implement Firebase email verification in my React app. Send a verification email after signup with a custom redirect URL. Create a useAuth hook that tracks verification status. Add Firestore security rules that require email_verified to be true for the posts collection.
Frequently asked questions
How often can I send verification emails to the same user?
Firebase rate-limits verification emails to 5 per hour per user. If the user exceeds this limit, they must wait before requesting another email.
Can I customize the verification email content?
Yes, go to Firebase Console > Authentication > Templates and edit the Email Verification template. You can change the subject line, body text, and sender name. For full HTML customization, use a custom SMTP server.
Does email verification work with other auth providers like Google?
Google, GitHub, and other OAuth providers typically provide verified emails. The emailVerified property is automatically set to true for these providers. You only need manual verification for email/password signups.
What happens if the user changes their email after verifying?
Changing the email via updateEmail or verifyBeforeUpdateEmail resets emailVerified to false. The user must verify the new email address. Use verifyBeforeUpdateEmail to require verification before the change takes effect.
How do I handle users who sign up but never verify?
Firebase does not automatically delete unverified accounts. You can write a scheduled Cloud Function that queries users via the Admin SDK and deletes accounts that remain unverified after a set period.
Can RapidDev help build a complete authentication flow with email verification?
Yes, RapidDev's team can implement end-to-end Firebase Auth flows including email verification, custom email templates, and server-side enforcement via security rules.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation