Implementing Authentication with Firebase in a Next.js App
Saturday, January 25, 2025
Authentication is a core feature in most modern web applications, and Firebase Authentication makes it easy to implement user authentication with various providers like Email/Password, Google, and more. In this tutorial, we'll walk through how to integrate Firebase Authentication into a Next.js app, covering everything from setup to protecting routes and displaying user data.
Setting Up Firebase
To get started, you'll need to set up a Firebase project.
Create a Firebase Project
Get Your Firebase Config
const firebaseConfig = {
apiKey: "your-api-key",
authDomain: "your-app.firebaseapp.com",
projectId: "your-project-id",
storageBucket: "your-app.appspot.com",
messagingSenderId: "your-sender-id",
appId: "your-app-id",
};
Installing Firebase in Your Next.js Project
Install Firebase SDK
Run the following command to install the Firebase library:
npm install firebase
Set Up Firebase Client Initialization
Create a firebase.js file in your project to initialize Firebase:
import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";
const firebaseConfig = {
apiKey: "your-api-key",
authDomain: "your-app.firebaseapp.com",
projectId: "your-project-id",
storageBucket: "your-app.appspot.com",
messagingSenderId: "your-sender-id",
appId: "your-app-id",
};
const app = initializeApp(firebaseConfig);
const auth = getAuth(app);
export { auth };
Implementing Authentication
User Registration
Create a function to register users:
import { createUserWithEmailAndPassword } from "firebase/auth";
import { auth } from "./firebase";
export const registerUser = async (email, password) => {
try {
const userCredential = await createUserWithEmailAndPassword(auth, email, password);
console.log("User registered:", userCredential.user);
} catch (error) {
console.error("Error registering user:", error);
}
};
User Login
Similarly, create a function to handle user login:
import { signInWithEmailAndPassword } from "firebase/auth";
export const loginUser = async (email, password) => {
try {
const userCredential = await signInWithEmailAndPassword(auth, email, password);
console.log("User logged in:", userCredential.user);
} catch (error) {
console.error("Error logging in user:", error);
}
};
Managing Authentication State
Use Firebase's onAuthStateChanged to listen for authentication changes:
import { onAuthStateChanged } from "firebase/auth";
import { auth } from "./firebase";
onAuthStateChanged(auth, (user) => {
if (user) {
console.log("User is signed in:", user);
} else {
console.log("No user signed in.");
}
});
Protecting Pages and API Routes
Protecting Client-Side Pages
Redirect unauthenticated users by checking the auth state in Next.js pages:
import { useRouter } from "next/router";
import { useEffect } from "react";
import { onAuthStateChanged } from "firebase/auth";
import { auth } from "../firebase";
const ProtectedPage = () => {
const router = useRouter();
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, (user) => {
if (!user) {
router.push("/login");
}
});
return () => unsubscribe();
}, [router]);
return <div>Welcome to the protected page!</div>;
};
export default ProtectedPage;
Protecting API Routes
Secure API routes by verifying Firebase tokens server-side:
import { getAuth } from "firebase-admin/auth";
const adminAuth = getAuth();
export default async function handler(req, res) {
const token = req.headers.authorization?.split("Bearer ")[1];
try {
const decodedToken = await adminAuth.verifyIdToken(token);
console.log("Decoded token:", decodedToken);
res.status(200).json({ message: "Authenticated!" });
} catch (error) {
res.status(401).json({ error: "Unauthorized" });
}
}
Adding Social Authentication (Optional)
If you'd like to add Google sign-in, enable it in Firebase Console and add the following:
import { GoogleAuthProvider, signInWithPopup } from "firebase/auth";
export const googleSignIn = async () => {
const provider = new GoogleAuthProvider();
try {
const result = await signInWithPopup(auth, provider);
console.log("Google sign-in successful:", result.user);
} catch (error) {
console.error("Error during Google sign-in:", error);
}
};
Displaying User Info
Show user details in your app:
const UserProfile = () => {
const [user, setUser] = useState(null);
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, (user) => {
setUser(user);
});
return () => unsubscribe();
}, []);
return user ? (
<div>
<p>Welcome, {user.displayName || user.email}!</p>
<button onClick={() => auth.signOut()}>Logout</button>
</div>
) : (
<p>Please log in.</p>
);
};
Wrapping Up
In this tutorial, we implemented Firebase Authentication in a Next.js app, covering setup, authentication, route protection, and user state management. Firebase's seamless integration with Next.js allows you to build secure and scalable applications. Experiment with additional features like multi-factor authentication or custom claims to further enhance your app.