Skip to content

Firebase Authentication Guide: Email, Google & Phone Sign-In Explained

DodaTech Updated Jun 6, 2026 7 min read

Firebase Authentication provides ready-to-use sign-in methods including email, Google, and phone — handling token generation and user identity in a few SDK calls.

What You’ll Learn

  • Setting up Firebase Authentication with multiple providers
  • Email/password sign-up, sign-in, and sign-out
  • Google OAuth and social login integration
  • Phone number authentication with SMS
  • User management, ID tokens, and security best practices

Why Firebase Authentication Matters

Building authentication from scratch means hashing passwords, managing sessions, handling token refresh, implementing OAuth flows, securing against brute force, and complying with data protection laws. Firebase Authentication handles all of this out of the box. DodaTech’s Durga Antivirus Pro uses Firebase Auth so users can sign in with email or Google — the SDK manages tokens, session persistence, and even remembers users across browser restarts.

    flowchart LR
    A["User"] -->|"Sign in with Email"| B["Firebase Auth"]
    A -->|"Sign in with Google"| B
    A -->|"Phone OTP"| B
    B -->|"Returns ID Token"| C["Client App"]
    C -->|"Token in requests"| D["Security Rules\n& Cloud Functions"]
    style A fill:#dbeafe,stroke:#2563eb
    style B fill:#fef3c7,stroke:#d97706
    style C fill:#dcfce7,stroke:#16a34a
    style D fill:#fce7f3,stroke:#ec4899
  
Prerequisites: A Firebase project from the Firebase Overview. Basic JavaScript familiarity.

Enabling Authentication Providers

  1. In the Firebase Console, go to Authentication > Sign-in method
  2. Click Email/Password and enable it
  3. Click Google and configure the OAuth consent screen
  4. Click Phone and add your test phone numbers

Each provider takes seconds to configure. No OAuth callback servers, no token exchange endpoints — just toggle and go.

Email/Password Authentication

Sign Up

import { createUserWithEmailAndPassword, updateProfile } from 'firebase/auth';

async function signUp(email, password, displayName) {
  try {
    const userCredential = await createUserWithEmailAndPassword(auth, email, password);
    // Add display name after account creation
    await updateProfile(userCredential.user, { displayName });
    
    console.log('Welcome,', displayName);
    return userCredential.user;
  } catch (error) {
    // Firebase returns specific error codes
    console.error('Error:', error.code);
    // 'auth/email-already-in-use' — account exists
    // 'auth/weak-password' — password too short
    // 'auth/invalid-email' — malformed email
  }
}

Sign In

import { signInWithEmailAndPassword } from 'firebase/auth';

async function signIn(email, password) {
  try {
    const userCredential = await signInWithEmailAndPassword(auth, email, password);
    console.log('Signed in as:', userCredential.user.email);
    return userCredential.user;
  } catch (error) {
    if (error.code === 'auth/user-not-found') {
      console.error('No account with this email');
    } else if (error.code === 'auth/wrong-password') {
      console.error('Incorrect password');
    } else {
      console.error('Error:', error.message);
    }
  }
}

Sign Out

import { signOut } from 'firebase/auth';

async function signOutUser() {
  await signOut(auth);
  // User is signed out — update UI to show login screen
  console.log('Signed out');
}

You might be wondering: “What happens to the user’s session after they close the browser?” Firebase persists the auth state by default — when the user returns, onAuthStateChanged fires with the restored user object. No token management needed.

Google OAuth Authentication

import { GoogleAuthProvider, signInWithPopup } from 'firebase/auth';

async function signInWithGoogle() {
  const provider = new GoogleAuthProvider();
  provider.addScope('email'); // Request additional scopes if needed
  
  try {
    const result = await signInWithPopup(auth, provider);
    // result.user — the signed-in user
    // result.credential — Google OAuth access token (if needed)
    console.log('Signed in with Google:', result.user.displayName);
  } catch (error) {
    if (error.code === 'auth/popup-closed-by-user') {
      console.error('User closed the popup');
    } else {
      console.error('Google sign-in error:', error.message);
    }
  }
}

Popup vs Redirect: Use signInWithPopup for desktop and signInWithRedirect for mobile or when popups are blocked. The redirect method navigates away and back after authentication.

Phone Authentication

import { RecaptchaVerifier, signInWithPhoneNumber } from 'firebase/auth';

// Initialize reCAPTCHA verifier
const verifier = new RecaptchaVerifier('recaptcha-container', {
  size: 'invisible'
}, auth);

async function sendPhoneOTP(phoneNumber) {
  try {
    const confirmation = await signInWithPhoneNumber(auth, phoneNumber, verifier);
    // Store `confirmation` for later OTP verification
    window.confirmationResult = confirmation;
    console.log('OTP sent to', phoneNumber);
  } catch (error) {
    console.error('Phone auth error:', error.message);
  }
}

// Verify OTP
async function verifyOTP(code) {
  try {
    const result = await window.confirmationResult.confirm(code);
    console.log('Phone verified:', result.user.phoneNumber);
  } catch (error) {
    console.error('Invalid OTP:', error.message);
  }
}

User State Management

import { onAuthStateChanged } from 'firebase/auth';

// This runs on every auth state change
// (sign-in, sign-out, token refresh, page load)
onAuthStateChanged(auth, (user) => {
  if (user) {
    // User is signed in
    console.log('User:', user.uid, user.email, user.displayName);
    updateUIForSignedIn(user);
  } else {
    // User is signed out
    console.log('No user');
    updateUIForSignedOut();
  }
});

Common Mistakes

1. Not Handling All Auth Error Codes

auth/user-not-found, auth/wrong-password, auth/too-many-requests — each needs a different user-facing message. A generic “Error signing in” is unhelpful.

2. Forgetting to Initialize reCAPTCHA for Phone Auth

Phone authentication requires reCAPTCHA to prevent abuse. Without it, phone auth fails silently. Initialize the verifier before calling signInWithPhoneNumber.

3. Storing User Data Locally Instead of Using Firebase

Some developers store user profile data in localStorage and keep it out of sync with Firebase. Always use onAuthStateChanged as the source of truth for auth state.

4. Ignoring Token Refresh

Firebase ID tokens expire after 1 hour. The SDK handles refresh automatically, but custom backends that verify tokens must handle expiration with token refresh via user.getIdToken(true).

5. Not Using Anonymous Auth

Anonymous auth (sign-in without credentials) lets users try your app before committing. Later, you can upgrade the anonymous account to a permanent provider.

Practice Questions

  1. What three authentication providers does Firebase support out of the box?
  2. Why does Firebase use ID tokens instead of server-side sessions?
  3. What does onAuthStateChanged do and why is it important?
  4. How does phone authentication prevent abuse?
  5. What happens when a Firebase ID token expires?

Answers:

  1. Email/password, social (Google, Facebook, GitHub, Twitter), and phone (SMS).
  2. ID tokens are stateless — they contain user identity signed by Firebase. The server verifies the signature without database lookups, aligning with REST statelessness.
  3. It’s an observer that fires whenever auth state changes (sign-in, sign-out, page load). It’s the single source of truth for user state in the UI.
  4. Phone auth requires reCAPTCHA verification before sending SMS, preventing bots from spamming phone numbers.
  5. The SDK automatically refreshes expired tokens. For custom backends, call getIdToken(true) to force a refresh before making authenticated requests.

Challenge: Implement a complete auth flow for Durga Antivirus Pro: email/password sign-up with displayName, Google sign-in, persistent auth state across page reloads, and sign-out that clears the UI. Show the security rule that restricts Firestore access to authenticated users only.

FAQ

Is Firebase Authentication secure enough for production?
: Yes — Firebase Auth follows industry standards (OAuth 2.0, OIDC), encrypts passwords with bcrypt, handles token signing with RS256, and is SOC 2 and HIPAA compliant. It’s used by millions of apps in production.
Can I use Firebase Auth with my own backend?
: Yes. Your backend verifies Firebase ID tokens using the Firebase Admin SDK (admin.auth().verifyIdToken(token)). This lets you use Firebase Auth for the frontend while keeping business logic on your server.
How do I handle user roles and permissions?
: Firebase Auth doesn’t have built-in roles. Store role information in Firestore (e.g., users/{uid}/role: "admin") and check it in Security Rules or Cloud Functions. Custom claims (admin.auth().setCustomUserClaims(uid, {role: "admin"})) are another option.
What happens if a user deletes their account?
: Call user.delete() to remove the auth account. The user can no longer sign in. Clean up their Firestore data separately — Firebase Auth doesn’t automatically delete Firestore documents.

Try It Yourself

Add auth to an HTML file:

<!DOCTYPE html>
<html>
<body>
  <div id="auth-section">
    <input id="email" placeholder="Email">
    <input id="password" type="password" placeholder="Password">
    <button onclick="signUp()">Sign Up</button>
    <button onclick="signIn()">Sign In</button>
  </div>
  <div id="user-section" style="display:none">
    <p id="displayName"></p>
    <button onclick="signOutUser()">Sign Out</button>
  </div>

  <script type="module">
    import { initializeApp } from "https://www.gstatic.com/firebasejs/10/firebase-app.js";
    import { getAuth, createUserWithEmailAndPassword, signInWithEmailAndPassword, signOut, onAuthStateChanged } from "https://www.gstatic.com/firebasejs/10/firebase-auth.js";

    const app = initializeApp({ /* your config */ });
    const auth = getAuth(app);

    window.signUp = () => createUserWithEmailAndPassword(auth, email.value, password.value);
    window.signIn = () => signInWithEmailAndPassword(auth, email.value, password.value);
    window.signOutUser = () => signOut(auth);

    onAuthStateChanged(auth, user => {
      document.getElementById('auth-section').style.display = user ? 'none' : 'block';
      document.getElementById('user-section').style.display = user ? 'block' : 'none';
      document.getElementById('displayName').textContent = user ? `Hello, ${user.email}` : '';
    });
  </script>
</body>
</html>

What’s Next

TopicDescription
Firestore & Realtime DatabaseStore user data and app content securely
Security Rules & HostingProtect data and deploy your app
Firestore Queries & IndexingQuery, filter, and sort data efficiently
RESTful APIsCompare Firebase Auth with JWT authentication

What’s Next

Congratulations on completing this Firebase Authentication tutorial! Here’s where to go from here:

  • Practice daily — Consistency is more important than long study sessions
  • Build a project — Apply what you learned by building something real
  • Explore related topics — Check out other tutorials in the same category
  • Join the community — Discuss with other learners and share your progress

Remember: every expert was once a beginner. Keep coding!

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro