Back to roadmaps authjs Course

Configuring Custom CredentialsProvider for Password Login

If you want users to log in with a username/email and password stored in your local database, configure the Credentials Provider.


1. Safety Considerations

  • Password Hashing: Never store passwords as plain text in your database. Always hash passwords before database writes using encryption libraries (such as bcrypt or argon2).
  • Session Strategy: When utilizing the Credentials provider, Auth.js defaults to using a JWT session strategy since database sessions cannot be securely verified without database adapter connections.

2. Configuration Setup (auth.ts)

Configure credentials options and define the authorize callback:

// auth.ts
import NextAuth from "next-auth";
import Credentials from "next-auth/providers/credentials";
import { prisma } from "./lib/prisma";
import bcrypt from "bcryptjs";

export const { handlers, signIn, signOut, auth } = NextAuth({
  providers: [
    Credentials({
      name: "credentials",
      credentials: {
        email: { label: "Email", type: "email", placeholder: "user@example.com" },
        password: { label: "Password", type: "password" },
      },
      // Execute credentials verification logic
      async authorize(credentials) {
        if (!credentials?.email || !credentials?.password) {
          return null;
        }

        // 1. Fetch the user profile from local database
        const user = await prisma.user.findUnique({
          where: { email: credentials.email as string },
        });

        if (!user || !user.hashedPassword) {
          return null;
        }

        // 2. Verify password correctness
        const isPasswordCorrect = await bcrypt.compare(
          credentials.password as string,
          user.hashedPassword
        );

        if (!isPasswordCorrect) {
          return null;
        }

        // 3. Return the authorized user object (saved inside JWT session payload)
        return {
          id: user.id,
          email: user.email,
          name: user.name,
        };
      },
    }),
  ],
  session: {
    strategy: "jwt",
  },
});
Published on Last updated: