Implementing Authentication in Next.js 15: A Comprehensive Guide

Next.js 15 continues to build on its reputation as a powerful full-stack framework, offering seamless integration with modern authentication solutions. Whether you're building a simple app or an enterprise-grade system, this guide will walk you through implementing authentication using Next.js 15 with popular tools like Auth.js (NextAuth.js), Clerk, and Supabase Auth.


Why Authentication Matters in Next.js

Authentication ensures secure user access to your application. Next.js 15 supports multiple authentication patterns:

  • Session-based (e.g., NextAuth.js)
  • Token-based (e.g., Supabase, Firebase)
  • Third-party services (e.g., Clerk, Auth0)

Option 1: Using Auth.js (NextAuth.js)

Auth.js (formerly NextAuth.js) is the most popular authentication library for Next.js.

Step 1: Install Dependencies

npm install next-auth @auth/core

Step 2: Configure Auth.js

import NextAuth from "next-auth";
import GoogleProvider from "next-auth/providers/google";

export const { handlers, auth, signIn, signOut } = NextAuth({
  providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID!,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
    }),
  ],
  secret: process.env.AUTH_SECRET!,
});

Step 3: Add Session Provider

Wrap your root layout with SessionProvider in app/layout.tsx:

import { SessionProvider } from "next-auth/react";

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>
        <SessionProvider>{children}</SessionProvider>
      </body>
    </html>
  );
}

Step 4: Protect Routes

Use middleware in middleware.ts:

export { auth as middleware } from "@/auth";

Step 5: Client-Side Authentication

Example login button in a client component:

"use client";
import { useSession, signIn, signOut } from "next-auth/react";

export default function AuthButton() {
  const { data: session } = useSession();

  return (
    <div>
      {!session ? (
        <button onClick={() => signIn("google")}>Sign in with Google</button>
      ) : (
        <button onClick={() => signOut()}>Sign out</button>
      )}
    </div>
  );
}

Best Practices

  • Use HTTPS in Production: Ensure all authentication flows use HTTPS.

  • Secure Session Storage: Use HTTP-only cookies for session tokens.

  • Role-Based Access Control: Implement middleware for protected routes:

// middleware.ts
import { auth } from "@/auth";

export default auth((req) => {
  if (!req.auth) return Response.redirect(new URL("/login", req.url));
});
  • Logging: Monitor authentication attempts for security insights.

Conclusion

Next.js 15 simplifies authentication with flexible options:

  • **Auth.js for open-source, self-hosted solutions

Clerk for rapid development with pre-built components

Supabase for all-in-one backend services

Choose the method that aligns with your project’s needs and security requirements. For more details, refer to the Next.js Authentication Documentation.