Firebase Authentication Guide: Email, Google & Phone Sign-In Explained
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
Enabling Authentication Providers
- In the Firebase Console, go to Authentication > Sign-in method
- Click Email/Password and enable it
- Click Google and configure the OAuth consent screen
- 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
- What three authentication providers does Firebase support out of the box?
- Why does Firebase use ID tokens instead of server-side sessions?
- What does
onAuthStateChangeddo and why is it important? - How does phone authentication prevent abuse?
- What happens when a Firebase ID token expires?
Answers:
- Email/password, social (Google, Facebook, GitHub, Twitter), and phone (SMS).
- ID tokens are stateless — they contain user identity signed by Firebase. The server verifies the signature without database lookups, aligning with REST statelessness.
- 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.
- Phone auth requires reCAPTCHA verification before sending SMS, preventing bots from spamming phone numbers.
- 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
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
| Topic | Description |
|---|---|
| Firestore & Realtime Database | Store user data and app content securely |
| Security Rules & Hosting | Protect data and deploy your app |
| Firestore Queries & Indexing | Query, filter, and sort data efficiently |
| RESTful APIs | Compare 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