Auth.js: Authenticate with Custom Credentials
The Auth.js Credentials provider lets you authenticate against your own system, like a user database. It's for when OAuth isn't an option and you need full control. The footgun: you are entirely responsible for the security of the login logic.
WHY IT EXISTS It provides a flexible authentication method when standard OAuth providers like Google or GitHub are not an option. It's designed for integration with existing, proprietary, or legacy user systems where you need to control the authentication logic directly.
THE MENTAL MODEL Think of the Credentials provider not as a complete authentication solution, but as a secure entry point into the Auth.js ecosystem. Auth.js gives you the sign-in page and session management, but you provide the locked box and the key—the authorize function—to decide who gets in. Auth.js doesn't look inside your box; it trusts your function's verdict.
HOW IT WORKS You configure the Credentials provider in your Auth.js setup. First, you define the credentials object, which specifies the form fields for your sign-in page (e.g., username, password). Second, you implement the authorize function. This async function receives the user's submitted credentials. Inside this function, you perform your validation by calling your own API, querying a database, or checking a hardware key. If the credentials are valid, you return a user object. If they are invalid, you return null or throw a custom error to deny access.
WHEN TO USE IT Use the Credentials provider when you need to authenticate against a system you already have, such as an internal user database from a previous version of your application. It's also the right choice for implementing custom authentication flows that don't fit the OAuth model, like two-factor authentication with a YubiKey or integrating with a corporate directory.
WHEN NOT TO USE IT Avoid this provider if a standard OAuth provider is a viable option. OAuth providers have invested heavily in security and account recovery. Rolling your own authentication is complex and carries significant security responsibility. Also, do not use this if you expect Auth.js to manage the users in a database for you; by default, it does not persist users from the Credentials provider.
ONE CANONICAL EXAMPLE A common scenario is migrating a legacy application to Next.js that has an existing user database with hashed passwords. You would use the Credentials provider. Inside the authorize function, you'd connect to your database, find the user by their email, and use a library like bcrypt to compare the submitted password with the stored hash. If they match, you return the user's data; otherwise, you return null.
Read the original → authjs.dev
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.