HomeBytesheetsRoadmapsUI TemplatesUI ToolsStack Discussion
4 Topics
Chapter•22 Minutes

4. Credentials Provider and Password Verification

Implement safe credentials validation and understand exactly what the authorize function does and does not do.

What Credentials Provider Does

The Credentials provider lets you implement custom login logic. authorize(credentials, request) should return a minimal user object on success or null when credentials are rejected. It does not hash passwords, create a registration flow, rate-limit attempts, or automatically persist users.

Implement `authorize()` Against Your Backend

Use a trusted HTTPS backend for password verification. Normalize and validate input, send credentials only to that backend, handle unsuccessful responses, and return a stable user ID plus only the safe profile fields needed by the application.

Authorize implementation
async authorize(credentials) {
  const email = credentials?.email?.trim().toLowerCase();
  const password = credentials?.password;
  if (!email || typeof password !== "string" || !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, 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",
  };
}
💡 Change the endpoint and response contract to your actual backend. The server must check account status, rate limits, MFA where applicable, and password hashes.

Password Storage and Error Handling

Never store plaintext passwords or invent a hashing algorithm. Use a maintained password-hashing algorithm such as Argon2id or bcrypt in the trusted backend. Return generic errors for unknown accounts and wrong passwords to reduce account enumeration. Never log raw credentials.

Test Credentials Sign-In

Create a test account through your real backend and test both valid and invalid login attempts. A successful authorize return needs a stable id; returning null rejects login. Do not hard-code production credentials in source code.

Credentials are not a database

The Credentials provider does not create user records or automatically persist credentials-authenticated users. Your identity backend owns that lifecycle.