HomeBytesheetsRoadmapsUI TemplatesUI ToolsStack Discussion
6 Topics
Chapter•20 Minutes

2. Install and Configure NextAuth

Install the matching package, set secrets, create the catch-all API route, and confirm the auth endpoints work.

Create or Inspect a Pages Router Project

If you already have a Next.js Pages Router app, use it. Otherwise create a project and choose the Pages Router when prompted.

Create a project
npx create-next-app@latest nextauth-demo
cd nextauth-demo
💡 Choose the Pages Router if prompted.

Install NextAuth v4

Pin the major version so examples match the installed API.

Install

npm install next-auth@^4
💡 Use one package manager consistently.

Generate a Strong Secret

Generate a high-entropy secret for cryptographic operations and session protection. Keep it server-side and out of source control.

Generate secret
openssl rand -base64 32
💡 Copy the generated value into .env.local; do not use the sample text as a real secret.

Configure Environment Variables

Create .env.local at the project root. Add the Google credentials after creating them in the next chapter. AUTH_API_URL must be your real trusted backend.

File: `.env.local`
NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET=replace_with_generated_secret
GOOGLE_CLIENT_ID=replace_with_google_client_id
GOOGLE_CLIENT_SECRET=replace_with_google_client_secret
AUTH_API_URL=https://api.your-domain.example
💡 Do not use NEXT_PUBLIC_ for secrets. Restart the development server after environment changes.

Create the NextAuth API Route

Create pages/api/auth/[...nextauth].js. This catch-all route handles sign-in, sign-out, provider callbacks, CSRF, and session endpoints.

File: `pages/api/auth/[...nextauth].js`
import NextAuth from "next-auth";
import GoogleProvider from "next-auth/providers/google";
import CredentialsProvider from "next-auth/providers/credentials";

export const authOptions = {
  providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
    }),
    CredentialsProvider({
      name: "Email and password",
      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, image: user.image ?? null, role: user.role ?? "user" };
      },
    }),
  ],
  session: { strategy: "jwt" },
};

export default NextAuth(authOptions);
💡 This baseline assumes your backend responds with { user: { id, email, name, image, role } }. Adapt the endpoint and response parsing to your API. The backend must verify passwords securely.

Verify the Auth Endpoint

Run npm run dev and visit /api/auth/providers. It should list configured provider IDs. This confirms the route loads, but it does not prove Google credentials or the backend login flow works; test each flow separately.

Run development server
npm run dev
💡 Open http://localhost:3000/api/auth/providers in a browser.