# How to Enable Email Verification in Firebase Auth

- Tool: Firebase
- Difficulty: Beginner
- Time required: 10-15 min
- Compatibility: Firebase (Spark and Blaze plans), firebase v9+ modular SDK
- Last updated: March 2026

## TL;DR

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.

## Before you start

- 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

### 1. 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.

```
import { getAuth, createUserWithEmailAndPassword, sendEmailVerification } from 'firebase/auth'

const auth = getAuth()

async function signUpWithVerification(email: string, password: string) {
  const userCredential = await createUserWithEmailAndPassword(auth, email, password)
  const user = userCredential.user

  await sendEmailVerification(user)
  console.log('Verification email sent to', email)

  return user
}
```

**Expected result:** A verification email arrives in the user's inbox with a link to confirm their email address.

### 2. 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.

```
import { sendEmailVerification } from 'firebase/auth'

const actionCodeSettings = {
  url: 'https://your-app.com/verified',
  handleCodeInApp: false,
}

async function sendVerification(user: any) {
  await sendEmailVerification(user, actionCodeSettings)
}
```

**Expected result:** After clicking the verification link, users are redirected to your specified URL instead of the default Firebase page.

### 3. 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.

```
import { getAuth } from 'firebase/auth'

const auth = getAuth()

async function checkVerification() {
  const user = auth.currentUser
  if (!user) return false

  // Refresh the user's profile from the server
  await user.reload()

  if (user.emailVerified) {
    console.log('Email is verified')
    return true
  } else {
    console.log('Email is not yet verified')
    return false
  }
}
```

**Expected result:** The function returns true when the user has clicked the verification link, false otherwise.

### 4. 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.

```
import { useEffect, useState } from 'react'
import { getAuth, onAuthStateChanged, sendEmailVerification, User } from 'firebase/auth'

function useAuth() {
  const [user, setUser] = useState<User | null>(null)
  const [verified, setVerified] = useState(false)

  useEffect(() => {
    const auth = getAuth()
    const unsubscribe = onAuthStateChanged(auth, async (firebaseUser) => {
      if (firebaseUser) {
        await firebaseUser.reload()
        setUser(firebaseUser)
        setVerified(firebaseUser.emailVerified)
      } else {
        setUser(null)
        setVerified(false)
      }
    })
    return () => unsubscribe()
  }, [])

  const resendVerification = async () => {
    if (user && !user.emailVerified) {
      await sendEmailVerification(user)
    }
  }

  return { user, verified, resendVerification }
}
```

**Expected result:** Unverified users see a verification prompt with a resend button; verified users access the protected content.

### 5. 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.

```
// firestore.rules
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {

    // Only verified users can read or write posts
    match /posts/{postId} {
      allow read, write: if request.auth != null
        && request.auth.token.email_verified == true;
    }

    // Public data readable by anyone authenticated
    match /public/{docId} {
      allow read: if request.auth != null;
    }
  }
}
```

**Expected result:** Unverified users receive 'Missing or insufficient permissions' when trying to access protected collections.

## Complete code example

File: `email-verification.ts`

```typescript
import {
  getAuth,
  createUserWithEmailAndPassword,
  sendEmailVerification,
  onAuthStateChanged,
  User,
} from 'firebase/auth'

const auth = getAuth()

const ACTION_CODE_SETTINGS = {
  url: 'https://your-app.com/verified',
  handleCodeInApp: false,
}

export async function signUpAndVerify(
  email: string,
  password: string
): Promise<User> {
  const { user } = await createUserWithEmailAndPassword(auth, email, password)
  await sendEmailVerification(user, ACTION_CODE_SETTINGS)
  return user
}

export async function resendVerificationEmail(): Promise<void> {
  const user = auth.currentUser
  if (!user) throw new Error('No user signed in')
  if (user.emailVerified) throw new Error('Email already verified')
  await sendEmailVerification(user, ACTION_CODE_SETTINGS)
}

export async function isEmailVerified(): Promise<boolean> {
  const user = auth.currentUser
  if (!user) return false
  await user.reload()
  return user.emailVerified
}

export function onVerificationChange(
  callback: (verified: boolean) => void
): () => void {
  return onAuthStateChanged(auth, async (user) => {
    if (user) {
      await user.reload()
      callback(user.emailVerified)
    } else {
      callback(false)
    }
  })
}
```

## Common mistakes

- **Checking emailVerified without calling user.reload() first, seeing stale unverified status** — undefined Fix: Always call await user.reload() before reading emailVerified. The local auth token caches the old value until refreshed.
- **Not adding the redirect URL to Firebase's Authorized Domains list, causing the verification link to fail** — undefined Fix: Go to Firebase Console > Authentication > Settings > Authorized Domains and add your app's domain. Without this, Firebase rejects the redirect URL.
- **Only enforcing email verification on the client side, allowing API-level bypasses** — undefined Fix: 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

## 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.

---

Source: https://www.rapidevelopers.com/firebase-tutorial/how-to-enable-email-verification-in-firebase
© RapidDev — https://www.rapidevelopers.com/firebase-tutorial/how-to-enable-email-verification-in-firebase
