NextJS & Firebase Integration

Search for a command to run...

No comments yet. Be the first to comment.
If you're like me and love the smooth swipe animation between desktops (Spaces) on macOS — but hate how laggy or sluggish it feels sometimes — you're not alone. While Apple doesn’t let us tweak animation speed directly, I found two powerful tricks th...

Struck after installing application on mobile Solution (not sure which is the solution): a) STACKOVERFLOW adb reverse tcp:8081 tcp:8081 //Forward requests from your device b) Revoke USB debugging authorisations c) Clean Gradle (Guess, This is th...

When working with Node.js projects, you've probably run into frustrating dependency issues while installing packages. If you've seen errors related to peer dependencies, you're not alone. Thankfully, npm offers a couple of flags—--legacy-peer-deps an...
In the world of modern chat applications, real-time communication is key. Whether it's for a messaging platform, collaborative tool, or gaming app, WebSockets offer a persistent and efficient channel for two-way communication. But what happens when y...
Both are web frameworks for Node.js, but Fastify is designed from the ground up to be: 🔥 Faster, Lighter, and More Scalable than Express FeatureFastifyExpress.js 🚀 PerformanceMuch faster (measured benchmarks)Slower due to older architecture...
This project demonstrates how to integrate Firebase Authentication with a Next.js application, providing a secure and efficient way to manage user authentication. Firebase offers a robust backend-as-a-service platform, and its authentication module seamlessly handles user sign-ins, sign-outs, and session management.
Key Features:
AuthContext) to manage and share authentication state across the application..env.local.By following this guide, you'll set up a fully functional authentication system with protected routes and dynamic user session handling, all within the simplicity and performance of Next.js. Whether you're building a small project or a large-scale application, this setup is a solid foundation for adding authentication to your app.
Here's the suggested structure for a project that includes Firebase authentication in Next.js:
project-root/
├── components/
│ ├── AuthProvider.jsx
├── context/
│ ├── AuthContext.jsx
├── lib/
│ ├── firebase.js
├── middleware.ts
├── pages/
│ ├── _app.js
│ ├── index.js
│ ├── login.js
│ ├── dashboard.js
├── styles/
│ ├── globals.css
├── .env.local
├── next.config.js
├── package.json
lib/firebase.jsYour firebase.js file initializes Firebase. The code you've provided is correct and initializes the Firebase app only once. It also sets up the auth and db exports for authentication and Firestore usage.
Here's the lib/firebase.js file that initializes Firebase for your Next.js project:
// lib/firebase.js
import { initializeApp, getApps } from "firebase/app";
import { getAuth } from "firebase/auth";
import { getFirestore } from "firebase/firestore";
// Firebase configuration using environment variables
const clientCredentials = {
apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
};
// Initialize Firebase only if no apps are already initialized
let firebaseApp;
if (!getApps().length) {
firebaseApp = initializeApp(clientCredentials);
} else {
firebaseApp = getApps()[0];
}
// Export Firebase Auth and Firestore instances
export const auth = getAuth(firebaseApp);
export const db = getFirestore(firebaseApp);
Environment Variables:
.env.local and accessed using process.env.Firebase Initialization:
initializeApp function is called only if no Firebase apps are already initialized. This avoids reinitialization errors, which can occur during development due to hot reloading.Exported Modules:
auth: Provides Firebase Authentication features.db: Connects to Firestore, Firebase's NoSQL database.This file will serve as the core configuration for Firebase in your application. You can import auth and db from this file whenever you need to use Firebase Authentication or Firestore in your project.
context/AuthContext.jsxThis file will manage the authentication state using React Context.
import { createContext, useContext, useState, useEffect } from "react";
import { onAuthStateChanged } from "firebase/auth";
import { auth } from "../lib/firebase";
const AuthContext = createContext();
export function AuthProvider({ children }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, (user) => {
setUser(user);
setLoading(false);
});
return unsubscribe;
}, []);
return (
<AuthContext.Provider value={{ user, loading }}>
{children}
</AuthContext.Provider>
);
}
export function useAuth() {
return useContext(AuthContext);
}
middleware.tsYour middleware ensures users cannot access protected pages without logging in.
The code you've provided works perfectly. Just ensure cookies like isLoggedIn are set properly during login.
Here's the middleware.ts file for your Next.js project:
// middleware.ts
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
export function middleware(request: NextRequest) {
// Check if the user is authenticated by looking for the 'isLoggedIn' cookie
const isLoggedIn = request.cookies.get("isLoggedIn");
console.log("Authentication status (isLoggedIn):", isLoggedIn);
// Redirect to /login if the user is not logged in and tries to access protected routes
if (!isLoggedIn && request.nextUrl.pathname !== "/login") {
return NextResponse.redirect(new URL("/login", request.url));
}
// Proceed to the requested route if the user is authenticated or on the login page
return NextResponse.next();
}
// Apply middleware to all routes except /login
export const config = {
matcher: ["/((?!login).*)"], // Matches all routes except /login
};
isLoggedIn Cookie:
isLoggedIn, which should be set after a successful login.Redirection:
/login, they are redirected to the /login page.NextResponse.next():
/login.matcher Configuration:
/login.pages/_app.jsWrap your application with the AuthProvider.
import { AuthProvider } from "../context/AuthContext";
import "../styles/globals.css";
function MyApp({ Component, pageProps }) {
return (
<AuthProvider>
<Component {...pageProps} />
</AuthProvider>
);
}
export default MyApp;
pages/login.jsCreate a login page using Firebase Authentication.
import { useState } from "react";
import { signInWithEmailAndPassword } from "firebase/auth";
import { useRouter } from "next/router";
import { auth } from "../lib/firebase";
export default function Login() {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState("");
const router = useRouter();
const handleLogin = async (e) => {
e.preventDefault();
try {
await signInWithEmailAndPassword(auth, email, password);
document.cookie = "isLoggedIn=true"; // Set the cookie
router.push("/dashboard");
} catch (err) {
setError("Invalid credentials");
}
};
return (
<div>
<h1>Login</h1>
{error && <p>{error}</p>}
<form onSubmit={handleLogin}>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Email"
required
/>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Password"
required
/>
<button type="submit">Login</button>
</form>
</div>
);
}
pages/dashboard.jsA protected page that requires authentication.
import { useAuth } from "../context/AuthContext";
import { useRouter } from "next/router";
export default function Dashboard() {
const { user, loading } = useAuth();
const router = useRouter();
if (loading) return <p>Loading...</p>;
if (!user) {
router.push("/login");
return null;
}
return (
<div>
<h1>Welcome, {user.email}</h1>
<button
onClick={() => {
auth.signOut();
document.cookie = "isLoggedIn=; Max-Age=0"; // Clear the cookie
router.push("/login");
}}
>
Logout
</button>
</div>
);
}
.env.localEnvironment variables for Firebase configuration.
NEXT_PUBLIC_FIREBASE_API_KEY=your-api-key
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=your-auth-domain
NEXT_PUBLIC_FIREBASE_PROJECT_ID=your-project-id
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=your-storage-bucket
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=your-messaging-sender-id
NEXT_PUBLIC_FIREBASE_APP_ID=your-app-id
AuthContext to manage authentication globally.isLoggedIn cookie.This structure provides a secure and scalable authentication system for your Next.js project using Firebase.