NextJS Authentication with App Router and Firebase

Explore how to implement Next JS authentication using app router and firebase authentication.

NextJS Authentication with App Router and Firebase
NextJS Authentication with App Router and Firebase

Building modern web applications demands a seamless user experience. One of the key aspects of this experience is secure and efficient user authentication. Traditionally, setting up authentication in Next.js applications, especially with server-side sessions, has been a somewhat complex endeavor. The introduction of the app directory in Next.js 15, alongside the powerful App Router, promises to change this, offering a more streamlined and intuitive approach to authentication.

However, understanding how to leverage these new tools, particularly with external providers like Firebase, can seem daunting. How do we seamlessly integrate Firebase's authentication capabilities with the App Router's server-side functions? How can we securely manage user sessions and protect sensitive routes within this new architecture?

Solution Explanation:

This article will guide you through building robust and user-friendly authentication in your Next.js 15 application using the App Router, Firebase, and server-side sessions.

Here's a breakdown of the solution:

  1. Firebase Integration: We'll leverage Firebase Authentication for its ease of use and secure authentication methods. You'll learn how to set up Firebase in your project and utilize its email/password authentication system.
  2. App Router and Server Components: Next.js 15's App Router and server components provide a robust framework for handling authentication logic. We'll create server-side functions within the app directory to securely interact with Firebase and manage user sessions.
  3. Server-Side Sessions: For enhanced security and personalization, we'll implement server-side sessions using secure cookies. This ensures that sensitive user data is always protected and persists across page loads.
  4. Protected Routes and Redirects: You'll discover how to define protected routes within your application, granting access only to authenticated users. Unauthenticated users will be seamlessly redirected to the login page.

Example:

Imagine you're building an e-commerce application. Users should be able to sign up, log in, and access their profile and order history securely. We'll use Firebase to handle user creation, authentication, and manage user sessions.

Code Implementations (TypeScript):

1. Project Setup and Firebase Configuration:

npm install next@latest react react-dom firebase firebase-admin

Create a Firebase project, enable Email/Password sign-in, and obtain your Firebase configuration.

// firebase.ts
import { initializeApp } from 'firebase/app';
import { getAuth } from 'firebase/auth';
import { getFirestore } from 'firebase/firestore';

// Your Firebase configuration
const firebaseConfig = {
  // ...
};

// Initialize Firebase
const app = initializeApp(firebaseConfig);

// Initialize Firebase services
export const auth = getAuth(app);
export const db = getFirestore(app);

2. Server-Side Authentication Function (app/api/auth/[...nextauth]/route.ts):

import { NextRequest, NextResponse } from 'next/server';
import { auth } from '@/lib/firebase';
import { createUserWithEmailAndPassword, signInWithEmailAndPassword, UserCredential } from 'firebase/auth';

export async function POST(request: NextRequest) {
  const { email, password, mode } = await request.json();

  try {
    if (mode === 'signup') {
      const userCredential: UserCredential = await createUserWithEmailAndPassword(auth, email, password);
      // Additional logic like sending verification email
      return NextResponse.json({ success: true, user: userCredential.user });
    } else if (mode === 'signin') {
      const userCredential: UserCredential = await signInWithEmailAndPassword(auth, email, password);
      // Set up a secure session cookie here (implementation not shown for brevity) 
      return NextResponse.json({ success: true, user: userCredential.user });
    } else {
      return NextResponse.json({ success: false, error: 'Invalid mode' });
    }
  } catch (error) {
    return NextResponse.json({ success: false, error: error.message });
  }
}

3. Client-Side Authentication Form (app/login/page.tsx):

'use client'; // Required for client-side data fetching
import { useState } from 'react';

export default function LoginPage() {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');

  const handleSubmit = async (e) => {
    e.preventDefault();

    const response = await fetch('/api/auth/[...nextauth]', {
      method: 'POST',
      body: JSON.stringify({ email, password, mode: 'signin' }), // Or 'signup'
    });

    const data = await response.json();
    // Handle successful login/signup (e.g., redirect to home)
  };

  return (
    <form onSubmit={handleSubmit}>
      {/* Input fields for email and password */}
      <button type="submit">Login</button>
    </form>
  );
}

4. Protected Route (app/profile/page.tsx):

'use server'; // Indicates a server component
import { NextResponse } from 'next/server';

export default async function ProfilePage() {
  // Check if the user is authenticated (session validation logic)
  const isAuthenticated = true; // Replace with actual session check

  if (!isAuthenticated) {
    return NextResponse.redirect('/login'); 
  }

  return (
    <div>
      <h1>Welcome to your profile</h1>
    </div>
  );
}

Call to Action:

Start building secure and user-friendly Next.js applications today! Explore the power of the App Router, Firebase, and server-side sessions to enhance your authentication flow.

Conclusion:

By combining the capabilities of the Next.js App Router, Firebase Authentication, and server-side sessions, you can create a robust and secure authentication system for your web applications. This approach ensures a smooth user experience while protecting sensitive user information.