HomeBytesheetsRoadmapsUI TemplatesUI ToolsStack Discussion
4 Topics
Chapter•22 Minutes

9. TypeScript and Auth.js v5 Differences

Add type augmentation for custom fields and recognize the v5/App Router integration shape.

Type Custom Session and JWT Fields

If using TypeScript and adding id, role, or provider, augment the NextAuth types so the compiler matches runtime behavior.

File: `types/next-auth.d.ts`
import "next-auth";

declare module "next-auth" {
  interface Session {
    user: {
      id: string;
      role: string;
      name?: string | null;
      email?: string | null;
      image?: string | null;
    };
    provider?: string | null;
  }
  interface User { role?: string; }
}

declare module "next-auth/jwt" {
  interface JWT {
    userId?: string;
    role?: string;
    provider?: string;
  }
}
💡 Ensure the declaration file is included by tsconfig.json. Adjust optional fields to match your actual callbacks.

Important v5 Differences

Auth.js v5 commonly defines auth.ts with const { handlers, auth, signIn, signOut } = NextAuth(config). In the App Router, app/api/auth/[...nextauth]/route.ts exports the GET and POST handlers. Server-side session retrieval commonly uses auth(). In newer APIs, redirectTo is preferred over the deprecated callbackUrl option. Consult the migration guide and do not mix v4 and v5 code.

Keep the main implementation consistent

The complete Pages Router code in this tutorial targets NextAuth v4. Use the v5 docs end-to-end if your installed package is v5.

Minimal v5 App Router Shape

This is a migration reference only, not part of the runnable v4 Pages Router path. Complete the provider and callbacks using the current v5 docs for your release.

File shape: `auth.ts`
import NextAuth from "next-auth";
import Google from "next-auth/providers/google";
import Credentials from "next-auth/providers/credentials";

export const { handlers, auth, signIn, signOut } = NextAuth({
  providers: [
    Google,
    Credentials({
      credentials: {
        email: { label: "Email", type: "email" },
        password: { label: "Password", type: "password" },
      },
      async authorize(credentials) {
        if (!credentials?.email || !credentials?.password) return null;
        const response = await fetch(`${process.env.AUTH_API_URL}/auth/login`, {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ email: credentials.email, password: credentials.password }),
          cache: "no-store",
        });
        if (!response.ok) return null;
        const result = await response.json();
        const user = result?.user;
        if (!user?.id || !user?.email) return null;
        return { id: String(user.id), name: user.name ?? null, email: user.email };
      },
    }),
  ],
});

// app/api/auth/[...nextauth]/route.ts:
// export const { GET, POST } = handlers;
💡 This shows the export shape only. Use the actual current v5 documentation for complete callbacks, session settings, and your exact Next.js version.

Official Documentation

Use version-specific primary documentation:

The current Auth.js site focuses on v5 and later; use the v4 documentation for the main implementation here.