BlogAtlas Vector Search voted most loved vector database in 2024 Retool State of AI reportLearn more >>
MongoDB Developer
TypeScript
plus
Sign in to follow topics
MongoDB Developer Centerchevron-right
Developer Topicschevron-right
Languageschevron-right
TypeScriptchevron-right

NextAuth.js Authentication With MongoDB

Ahmed Bouchefra10 min read • Published Jul 03, 2024 • Updated Jul 03, 2024
MongooseNext.jsTypeScriptJavaScript
FULL APPLICATION
Facebook Icontwitter iconlinkedin icon
Rate this tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
NextAuth.js is a robust authentication library built for Next.js applications. It streamlines the integration of authentication functionalities and offers compatibility with numerous authentication methods, including OAuth providers (Google, Github, etc.), email/password logins, and more.
This tutorial guides you through setting up NextAuth.js for user authentication with email and password in your Next.js 14 application.
You can find the code from this GitHub repository.

Requirements

Before we dive in, make sure you have the following prerequisites:
  • Node.js v20: Make sure you have Node.js installed on your machine. You can download it from the official website.
  • React and Next.js 14: A basic understanding of React and Next.js 14 is helpful for this tutorial.
  • (Optional) Have MongoDB Community Edition 7.0 installed and running.
Ensure you have the mongodb-community service started locally. Alternatively, you can use a free-forever MongoDB Atlas cluster.

Creating the Next.js project

Let's create a new Next.js project using the following command in your terminal:
Answer the questions as follows:
After the prompts, create-next-app will create a folder with your project name and install the required dependencies.

Installing dependencies

Navigate inside your project and install the following dependencies:
The next-auth package provides authentication functionalities for Next.js applications. It offers built-in support for various authentication providers and allows for easy integration with your application.
The bcryptjs library provides functions for hashing passwords using the bcrypt algorithm. It's commonly used for securely storing passwords in databases by generating salted password hashes.
Mongoose is an object data modeling (ODM) library for MongoDB and Node.js. It provides a straightforward, schema-based solution to model your application data, making it easier to work with MongoDB databases.
After installing these dependencies, you'll have the necessary tools and libraries to set up authentication features in your Next.js application, integrate with MongoDB, securely hash passwords, and define data models using Mongoose.

Connecting to MongoDB

After installing the dependencies, it's time for connecting to MongoDB. Create a .env.local file in the root of your project and add your MongoDB connection string:
Note: If you are connecting to a MongoDB Atlas cluster, you can find your connection string in the Atlas dashboard.
Create a lib/mongodb.ts file and add the following code for connecting to a MongoDB database using mongoose:
We are importing the mongoose library, which is a popular ODM Node.js library for MongoDB. Next, we retrieve the MongoDB URI from the environment variables. Then, we define an asynchronous function named connectDB that connects to the MongoDB database using the URI obtained from the environment variables.
Inside the connectDB function, we use a try...catch block to handle any potential errors that may occur during the database connection process. Within the try block, we use mongoose.connect() to establish a connection to the MongoDB database using the provided URI. If the connection is successful, we resolve the promise with a value of true.
If any errors occur during the connection process, they are caught by the catch block. In this case, we log the error to the console and reject the promise with the caught error.
Next, create a models/User.ts file and start by adding the following imports:
Add the user interface:
Add the user schema:
This defines a Mongoose schema for a user document. The UserSchema specifies the structure and validation rules for user data stored in a MongoDB collection.
Finally, export the user model:
This ensures that the user model is defined and available for use in the application, either by retrieving an existing model or creating a new one based on the specified schema.

Configuring NextAuth.js

First, we need a NextAuth secret key. This secret key is used to encrypt JWT tokens and session data. You can get it simply by running this command on your terminal and it will generate a random key for you:
You need to copy the secret to your .env file:
Create a lib/auth.ts file and start by adding the following imports:
Define a NextAuth options object as follows:
In the authorize() function, add the following code:
This code verifies the user's credentials (email and password) against those stored in a MongoDB database. It ensures that the provided credentials are valid before allowing the user to proceed with authentication.
Next, create an app/api/auth/[...nextauth]/route.ts file and add the following code:
This code imports authentication options from their module, initializes the authentication handler using those options, and exports the handler to be used for both GET and POST requests in API routes.

Creating a server action for registering users

In Next.js, a server action refers to any logic or functionality that is executed on the server-side before rendering the page. This can include tasks such as fetching data from an external API, accessing a database, or performing authentication checks.
In our case, we'll create a server action for registering users. Inside the root of your project, create an actions/register.ts file and start by adding the following imports:
The "use server" directive, placed at the beginning of the file, instructs Next.js to treat the function(s) as a server action. This function can be called from client-side components, but it executes on the server.
Export a server action as follows:
The register function handles the process of registering a new user by connecting to the MongoDB database, checking for existing email addresses, hashing passwords, and saving user data to the database.

Creating pages

After setting up NextAuth and implementing a server action for user registration, the next step is to create the login and registration pages.

Login page

To begin with, let's focus on the login page. Create a file named app/login/page.tsx and begin by importing the necessary dependencies:
The use client directive is used to mark the component as client-side code. This means that the code within this scope will only be executed and available in the user's browser environment, not on the server.
Define a function and export it:
In the body of the function, start by adding the following code:
This establishes state management for error messages and access to the client-side router.
Add the handleSubmit() function as follows:
This defines an asynchronous function that handles form submission for user login. It prevents default form behavior, extracts user credentials from the form using FormData, attempts sign-in using NextAuth.js, and handles successful login by redirecting the user to the home page and potential errors by updating the component's error state.
Return the following JSX code:
This simply creates a form that allows users to input their email and password for authentication, and it provides a link to navigate to the registration page if they don't have an account yet.
This is what the form looks like: sign-in form

Registration page

Next, let's create the registration page. Create a app/register/page.tsx file and start by adding the following code:
This creates a client-side component that initializes state for error handling, utilizes Next.js router for navigation, and provides a reference to the form element, that will be created below, using a ref.
Add the handleSubmit() function:
This defines an asynchronous function named handleSubmit, which is called when a form is submitted. The function handles the form submission, including extracting form data using FormData, user registration by calling the register server action, error handling, and redirecting the user to the login page upon successful registration. Otherwise, it sets the error that will be displayed.
Return the following JSX code:
This is how it looks:
register form

Using the session provider and displaying the authentication state

In this section, we’ll demonstrate how to use the SessionProvider in the parent layout to ensure session management is available throughout the application. We’ll retrieve the authentication state from the session and dynamically display a "Sign Out" button if the user is authenticated, or a "Sign In" button if the user is not authenticated.
Create a app/provider.tsx file and add the following code:
Update the app/layout.tsx with the provider we created. First import it:
Then, add it as follows:
Update the app/page.tsx file as follows:
Update the app/globals.css file to remove custom CSS and only keeping the following:

Testing

You first need to register from this interface:
sign-in interface
You can then log in from this interface:
register interfact
You’ll be redirected to the home page with the “Sign Out” button that appears only when the user is logged in, and you can use it to log out from the app:
sign-out button

Conclusion

In this tutorial, we walked through the steps to set up NextAuth.js authentication with MongoDB as the backend database. We started by creating a new Next.js project and installing necessary dependencies. Then, we established a connection to MongoDB using Mongoose and defined a user schema to structure our user data.
Next, we configured NextAuth.js by generating a secret key, defining authentication options, and implementing the authorization logic to verify user credentials against MongoDB. We also created server actions for user registration, handling database operations securely on the server-side.
After configuring authentication, we created login and registration pages using React components and integrated them with NextAuth.js for authentication. We handled form submissions, error handling, and user redirection based on authentication status.
Finally, we updated the layout to include a session provider for managing user sessions and ensured proper display of authentication status on the home page.
By following these steps, you can effectively implement authentication in your Next.js application using NextAuth.js and MongoDB, providing a secure and seamless experience for your users while simplifying the authentication setup process for developers.
Want to continue the conversation? Head to the MongoDB Developer Community next.
Top Comments in Forums
There are no comments on this article yet.
Start the Conversation

Facebook Icontwitter iconlinkedin icon
Rate this tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
Related
Tutorial

Create a REST API with Cloudflare Workers and MongoDB Atlas


Mar 29, 2024 | 7 min read
Quickstart

Getting Started with Deno & MongoDB


May 22, 2024 | 12 min read
Tutorial

Using Expo and Realm React Native with expo-dev-client


Aug 26, 2022 | 3 min read
Tutorial

Build a CRUD API With MongoDB, Typescript, Express, Prisma, and Zod


Jun 12, 2024 | 10 min read
Table of Contents