Securely Manage User Access with NextAuth.js and Next.js: A Credential-Based Authentication Guide
Robust authentication is paramount for controlling access to your web applications. While OAuth providers (like Google or GitHub) are popular, email/password authentication remains a prevalent and secure choice. This guide details implementing credential-based authentication within a Next.js application using the powerful NextAuth.js library. We'll break down the process step-by-step for easy implementation in your own projects.
NextAuth.js is a streamlined authentication solution for Next.js, supporting both OAuth providers and, importantly for this tutorial, custom credential providers. The latter allows for email/password authentication, offering granular control over the login process.
The NextAuth.js Credential Provider provides:
Let's delve into the code implementation.
The NextAuthOptions
configuration object dictates NextAuth.js's authentication behavior. Here's the complete configuration code:
<code class="language-javascript">import { NextAuthOptions } from "next-auth"; import CredentialProvider from "next-auth/providers/credentials"; import bcrypt from "bcryptjs"; import { dbConnect } from "@/lib/dbConnect"; import UserModel from "@/model/User"; export const authOptions: NextAuthOptions = { providers: [ CredentialProvider({ id: "credentials", name: "Credentials", credentials: { email: { label: "Email", type: "text" }, password: { label: "Password", type: "password" }, }, async authorize(credentials: any): Promise<any> { await dbConnect(); try { const user = await UserModel.findOne({ $or: [ { email: credentials.identifier }, { username: credentials.identifier }, ], }); if (!user) { throw new Error("Invalid email or username"); } if (!user.isVerified) { throw new Error("Please verify your account."); } const isPasswordCorrect = await bcrypt.compare(credentials.password, user.password); if (isPasswordCorrect) { return user; } else { throw new Error("Incorrect password."); } } catch (err: any) { throw new Error(err.message); //Improved error handling } }, }), ], callbacks: { async jwt({ token, user }) { if (user) { token._id = user._id?.toString(); token.isVerified = user?.isVerified; token.username = user?.username; token.isAcceptingMessages = user?.isAcceptingMessages; } return token; }, async session({ session, token }) { if (token) { session.user._id = token._id?.toString(); session.user.isVerified = token?.isVerified; session.user.username = token?.username; session.user.isAcceptingMessages = token?.isAcceptingMessages; } return session; }, }, pages: { signIn: "/sign-in", error: "/sign-in", }, session: { strategy: "jwt", }, secret: process.env.NEXTAUTH_SECRET, };</code>
An API route is necessary to interface with NextAuth.js's authentication mechanisms.
<code class="language-javascript">// app/api/auth/[...nextauth]/route.ts import NextAuth from "next-auth"; import { authOptions } from "@/lib/authOptions"; const handler = NextAuth(authOptions); export { handler as GET, handler as POST };</code>
This concisely imports the configuration and exposes the handler for both GET and POST requests.
Maintain a well-organized project structure:
<code>/lib /authOptions.ts /model /User.ts /app /api /auth /[...nextauth]/route.ts</code>
The provided code snippet for the API route is already correctly configured for Next.js 13 using the App Router.
This comprehensive guide empowers you to implement secure credential-based authentication in your Next.js projects using NextAuth.js. The flexibility of the Credential Provider allows for complete control over the authentication flow, ensuring a robust and secure user experience. Remember to adapt the database connection (dbConnect
and UserModel
) to your specific setup.
The above is the detailed content of Implementing Credential-Based Authentication with NextAuth.js in Next.js. For more information, please follow other related articles on the PHP Chinese website!