Back to All Guides
Web Development11 min readPublished: August 14, 2026Updated: August 15, 2026

Secure Authentication in Next.js 15: Implementing Auth.js (NextAuth v5) with JWT & OAuth

Implement production authentication in Next.js 15 App Router using Auth.js (NextAuth v5). Learn OAuth providers, session callbacks, role-based route protection, and secure cookies.

Vyuhantrix Team
Vyuhantrix Team
Security & Full-Stack · Vyuhantrix

Modern Web Authentication with Auth.js (NextAuth v5)#

Authentication is the security backbone of any modern web application. In the Next.js App Router, authentication must work seamlessly across Server Components, Server Actions, Route Handlers, and Edge Middleware.

Auth.js (formerly NextAuth.js v5) has been completely rewritten from the ground up for Next.js 15 and universal JavaScript runtimes, providing lightweight OAuth (Google, GitHub), magic links, credential authentication, and encrypted JWT session cookies with zero client-side overhead.


1. Setting Up Auth.js Configuration (`auth.config.ts`)#

Separate your edge-compatible routing rules from database adapters:

typescript
import type { NextAuthConfig } from "next-auth";
import GitHub from "next-auth/providers/github";
import Google from "next-auth/providers/google";

export const authConfig: NextAuthConfig = {
  providers: [
    GitHub({
      clientId: process.env.AUTH_GITHUB_ID,
      clientSecret: process.env.AUTH_GITHUB_SECRET,
    }),
    Google({
      clientId: process.env.AUTH_GOOGLE_ID,
      clientSecret: process.env.AUTH_GOOGLE_SECRET,
    }),
  ],
  pages: {
    signIn: "/login", // Custom styled login page
    error: "/auth-error",
  },
  callbacks: {
    // 1. Authorize route access in Middleware
    authorized({ auth, request: { nextUrl } }) {
      const isLoggedIn = !!auth?.user;
      const isOnDashboard = nextUrl.pathname.startsWith("/dashboard");

      if (isOnDashboard) {
        if (isLoggedIn) return true;
        return false; // Redirect unauthenticated users to /login
      }
      return true;
    },

    // 2. Attach user role and ID to JWT
    async jwt({ token, user }) {
      if (user) {
        token.id = user.id;
        token.role = (user as any).role || "USER";
      }
      return token;
    },

    // 3. Expose claims to client/server session
    async session({ session, token }) {
      if (session.user) {
        session.user.id = token.id as string;
        (session.user as any).role = token.role as string;
      }
      return session;
    },
  },
};

2. Initializing Handlers (`auth.ts`)#

typescript
import NextAuth from "next-auth";
import { PrismaAdapter } from "@auth/prisma-adapter";
import { db } from "@/lib/prisma";
import { authConfig } from "./auth.config";

export const { handlers, auth, signIn, signOut } = NextAuth({
  adapter: PrismaAdapter(db),
  session: { strategy: "jwt" }, // High-speed stateless JWT sessions
  ...authConfig,
});

Create the API route handler at app/api/auth/[...nextauth]/route.ts:

typescript
import { handlers } from "@/auth";
export const { GET, POST } = handlers;

3. Protecting Routes with Edge Middleware (`middleware.ts`)#

Protect private routes at the edge before requests ever hit your server components:

typescript
import NextAuth from "next-auth";
import { authConfig } from "./auth.config";

export default NextAuth(authConfig).auth;

export const config = {
  matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
};

4. Accessing the Session in React Server Components#

In Next.js 15 Server Components, accessing the current authenticated user is an asynchronous one-liner:

tsx
import { auth } from "@/auth";
import { redirect } from "next/navigation";

export default async function DashboardPage() {
  const session = await auth();

  if (!session?.user) {
    redirect("/login");
  }

  return (
    <div className="p-8 text-white">
      <h1 className="text-2xl font-bold">Welcome back, {session.user.name}!</h1>
      <p className="text-white/60 text-sm">Role: {(session.user as any).role}</p>
    </div>
  );
}

5. Security Best Practices Checklist#

  • [ ] Store AUTH_SECRET generated via npx auth secret in production environment variables.
  • [ ] Use HttpOnly, Secure, and SameSite=Lax cookies (configured automatically by Auth.js).
  • [ ] Implement CSRF token validation on all credential mutation forms.
  • [ ] Avoid storing sensitive private tokens (like OAuth refresh tokens) in client-accessible session objects.

6. Real-World Sign-In Component with Social Buttons#

Here is how to create a clean, accessible sign-in UI with GitHub and Google OAuth triggers using Server Actions:

tsx
import { signIn } from "@/auth";

export function SignInButtons() {
  return (
    <div className="flex flex-col gap-4 max-w-sm mx-auto">
      <form
        action={async () => {
          "use server";
          await signIn("github", { redirectTo: "/dashboard" });
        }}
      >
        <button
          type="submit"
          className="w-full py-3 px-4 rounded-xl bg-white/10 hover:bg-white/15 border border-white/10 text-white font-semibold text-sm transition-all"
        >
          Sign In with GitHub
        </button>
      </form>

      <form
        action={async () => {
          "use server";
          await signIn("google", { redirectTo: "/dashboard" });
        }}
      >
        <button
          type="submit"
          className="w-full py-3 px-4 rounded-xl bg-brand-teal text-white font-semibold text-sm hover:bg-brand-teal/90 transition-all shadow-lg shadow-brand-teal/20"
        >
          Sign In with Google
        </button>
      </form>
    </div>
  );
}
Article Note & VerificationThis guide was written and reviewed by the Vyuhantrix Team for educational and practical accuracy. For framework-specific breaking changes, verify against the official documentation of the relevant project. Last updated: August 15, 2026. Disclaimer
Tags:#Next.js#Auth.js#Authentication#Security#OAuth#JWT
Vyuhantrix Team

Published by

Vyuhantrix Team

Security & Full-Stack · Vyuhantrix

Vyuhantrix is an open technology learning platform based in Ahmedabad, India, publishing step-by-step programming tutorials, system design breakdowns, and free developer tools.