Node.js User Authentication Guide
Want to authenticate and manage users with specific roles in your Node.js app? This in-depth tutorial explains everything step-by-step to help you implement authentication in your Node.js apps.

Table of Contents
- Introduction
- Goal
- Prerequisites
- Set Up a Mongo Database
- Set Up the Server
- Connect to the Database
- Create User Schema
- Perform CRUD Operations
- Register Function
- Set Up Register Route
- Test the Register Route
- Login Function
- Set Up Login Route
- Test the Login Route
- Update Function
- Set Up Update Route
- Testing the Update Route
- Delete Function
- Set up the deleteUser Route
- Test the deleteUser Route
- Hash User Passwords
- Refactor Register Function
- Test the Register Function
- Refactor the Login Function
- Test the Login Function
- Authenticate Users with JSON Web Token (JWT)
- Refactor the Register Function
- Refactor the Login Function
- Protect the Routes
- Admin Authentication
- Basic User Authentication
- Protect the Routes
- Populate the Database with Admin User
- Create the Login Form Using EJS
- Render Embedded JavaScript
- Create EJS Files
- Create a Home Page
- Create a Registration Form
- Add POST Request Functionality
- Create a Login Form
- Add POST Request Functionality
- Add Registered Users to the Route
- Display Registered User in user Route
- Add Update and Delete Function to the Admin Route
- Edit a User's Role
- Delete Users
- Logout Functionality
- Node.js Authentication with LoginRadius
- How to Authenticate Your Node.js App with LoginRadius
- Conclusion
- Resources
Introduction
Introduction
Creating a user registration form employs the management of the registered user. This is where user role authentication comes into play. Role authentication ensures that non-admin users cannot make changes or access exclusive information. It grants administrative privileges to admin users and basic privileges to basic users.
You can build your own authentication functionality with web tokens like JSON Web Token (JWT) or use a trusted third-party customer identity and access management (CIAM) software like LoginRadius.
Goal
This tutorial helps you:
- understand the differences between the Admin role and the Basic user role;
- use JWT to authenticate users; and
- learn role-based authentication using JWT in a simple Node.js app.
Prerequisites
You have installed the following:
You already understand JavaScript E56 Syntax.
Now that everything is in place, let's set up your database.
Set Up a Mongo Database
You'll store all your user data — which includes username, password, and role — in MongoDB.
Install a node package called Mongoose that will connect to MongoDB. Then create a user for your application.
sets up your new project and creates a file with the credentials.
After installing mongoose, create a new file in the project's directory and require .
With the help of mongoose, you can connect your application to MongoDB:
The code snippet here connects to and then specifies the name of the database .
The function awaits for the connection, which contains the and as a second parameter. If it connects without errors, it will log out . Error issues will be fixed while connecting to the database. After this, it exported the function for use in the server.
Set Up the Server
You need to install some dependencies that you'll use in this tutorial.
Express.js is a Node.js framework for building web applications quickly and easily.
Nodemon is a tool that watches the file system and automatically restarts the server when there is a change.
You require in your application to listen for a connection on port . Create a new file in the root directory and create the listening event:
The next step is to test your application. Open up your file and add the following to :
Open your terminal and run to start the server.
Connect to the Database
Earlier, you've created a function that connects to MongoDB and exported that function. Now import that function into your :
You also need to create an error handler that catches every error.
The listening event is assigned to a constant . If an error occurs, it logs out the error and closes the with an exit code of 1.
Create User Schema
Schema is like a blueprint that shows how the database will be constructed.
You'll structure a user schema that contains username, password, and role.
Create a new folder in the project's directory, and create a file called . Now open and create the user schema:
In the schema, the will be unique, required, and will accept .
You've specified the minimum characters(6) the field will accept. The field grants a default value (basic) that you can change if needed.
Now, you need to create a user model and export it:
You've created the user model by passing the as the second argument while the first argument is the name of the model .
Perform CRUD Operations
You'll create functions that handle:
- adding users;
- getting all users;
- updating the role of users; and,
- deleting users.
Register Function
As the name implies, this function will handle the registrations of users.
Let's create a new folder named . It will contain the Authentication file and the Route set-up file.
After creating the folder, add two files — and .
Now open up our file and import that model:
The next step is to create an function that will take the user's data and register it in the database.
You need to use an Express middleware function that will grant access to the user's data from the body. You'll use this function in the file:
Let's go back to your file and create the register function:
The exported function will be used to set up the routes. You got the username and password from the and created a block that will create the user if successful; else, it returns status code with the error message.
Set Up Register Route
You'll create a route to using . Import the function into your file, and use it as the route's function:
The last step is to import your file as middleware in :
The server will use the middleware function if there is a request to .
Test the Register Route
You'll use Postman to test all the routes.
Open up Postman to send a request to and pass the username and password to the body:
Login Function
You've created a function that adds registered users to the database. You have to create another function that will authenticate user credentials and check if the user is registered.
Open the file and create the Login function, as follows:
The function returns status code if the username and password were not provided. You need to find a user with the provided and :
Here, it returns status code when a user isn't found and when a user is found. The code snippet wrapped all this in a block to detect and output errors, if any.
Set Up Login Route
To set up the login route, import the function into your :
Test the Login Route
Make a request at and pass a valid username and password to the body:
Update Function
This function will be responsibile for updating the role of a basic user to an admin user. Open the file and create the function, as follows:
The first statement verifies if and are present in the request body.
The second statement checks if the value of is admin. You should do this to avoid having over two roles.
After finding a user with that ID, you'll create a third block that will check for the role of the user:
The third block prevents assigning an admin role to an admin user, while the last block checks if an error occurred when saving the role in the database.
The numerous statements might be a little bit tricky but understandable. Please read the comments in the above code block for better understanding.
Set Up Update Route
Import the function in your , as follows:
Testing the Update Route
Send a request to :
Delete Function
The function will remove a specific user from the database. Let's create this function in our file:
You remove the user based on the you get from .
Set up the Route
Open your file to create a request to , using the as its function:
Test the Route
Send a request to by passing a valid to the body:
Hash User Passwords
Saving user passwords in the database in plain text format is reckless. It is preferable to hash your password before storing it.
For instance, it will be tough to decipher the passwords in your database if they are leaked. Hashing passwords is a cautious and reliable practice.
Let's use to hash your user passwords.
Lets install :
After installing , import it into your
Refactor Register Function
Instead of sending a plain text format to your database, lets hash the password using :
takes in your password as the first argument and the number of times it will hash the password as the second argument. Passing a large number will take a long time to hash the password, so give a moderate number like 10.
will return a promise with the hashed password; then, send that hashed password to the database.
Test the Register Function
Send a request to and pass the username and password to the body:
Refactor the Login Function
checks if the given password and the hashed password in the database are the same.
Test the Login Function
Send a request to and pass a valid username and password to the body:
Authenticate Users with JSON Web Token (JWT)
JSON Web Token helps shield a route from an unauthenticated user. Using JWT in your application will prevent unauthenticated users from accessing your users' home page and prevent unauthorized users from accessing your admin page.
JWT creates a token, sends it to the client, and then the client uses the token for making requests. It also helps verify that you're a valid user making those requests.
You've to install JWT before using it in your application:
Refactor the Register Function
When a user registers, you'll send a token to the client using JWT as a cookie. To create this token, you need to set a secret string. You'll use the node's in-built package called to create random strings:
Output:
Storing this secret string in an environment variable is a safe practice. If this secret string is leaked, unauthenticated users can create fake tokens to access the route.
Store your secret string in a variable:
Once you've created your , import as the token in the function:
The code snippet created the token using JWT's function. This function takes in three parameters:
-
the payload is the first parament that you'll pass to the function. This payload holds data concerning the user, and this data should not contain sensitive information like passwords;
-
you passed your as the second parameter; and,
-
how long the token will last as the third parameter.
After passing all these arguments, JWT will generate a token. After the token is generated, send it as a cookie to the client.
Refactor the Login Function
Also, generate a token for logged in users:
Protect the Routes
To prevent unauthenticated users from accessing the private route, take the token from the cookie, verify the token, and redirect users based on role.
You'll get the token from the client using a node package called . Let's install the package before using it:
After installing it, import it into your file and use it as a middleware:
You'll create your middleware that verifies the token and grants access to your private route.
Let's create a new folder in the project's folder named and create a file called .
Admin Authentication
Open the file and create the middleware:
The code snippet requests a token from the client, checks if a token is available, and verifies that token.
JWT verifies your token with your and returns a callback function. This function returns status code if the token fails the authentication test.
When you've created the token, you passed a payload that contained the user's credentials. You'll get the role from the credentials and check if the user's role is admin. If the user is not an admin, you return status code , but you'll call the function if the user is an admin.
Basic User Authentication
You'll also authenticate basic users before granting them access to the users route. Let's create another middleware in your file that will authenticate basic users:
Protect the Routes
You'll have two routes: one for the user and the other for the admin. Let's import this middleware into your file and protect your routes:
Updating user roles and deleting users should be done by an Admin, so you need to import this middleware into your file to protect the and routes.
:
Populate the Database with Admin User
You need to create an admin user in your database. Open up your terminal, and let's run some MongoDB methods:
After mongo is started, you need to use the database:
Before adding your admin user to the database, you need to hash the password using in the terminal. Open node terminal in your project's directory:
After you've created the constant , you need to enter in the node terminal to get your hashed password.
You'll use the hashed password to create your admin:
To check if it was successfully created, run — this will output all users in the database.
Create the Login Form Using EJS
You'll use Embedded JavaScript (EJS) to create a front-end for your application.
Install the package:
After you've installed , you need to set as your default view engine in your file:
Render Embedded JavaScript
When making a request to specific routes, you'll render an file:
Create EJS Files
By default, your application will look into the folder when rendering an file. You need to create the folder in your project's folder and add your files to it
Create a Home Page
Your home page will contain the links to and ejs file. Open up and add these links:
Create a Registration Form
Embedded JavaScript (EJS) supports HTML syntax. You'll create the registration form in using HTML syntax:
Add POST Request Functionality
You need to get the username and password that the user entered and pass it to the body when making the request:
The code snippet uses JavaScript's in-built library called to send a POST request to .
After the request has been sent, it stores the response to a constant .
will return the JSON you've passed as a response in the API.
When returns the data, you store that data in a constant .
If you get an error while making the request, display the error to the user. If an error isn't found, redirect the user based on their role on different routes.
Create a Login Form
Creating your login form and adding functionality to it will be similar to that of your registration. Open and create this form:
Add POST Request Functionality
Add Registered Users to the Route
Once you've redirected users based on role to different routes, display all registered users on that route. You need to send a request to .
Open file in folder:
The method returns an array of users. After mapping through this array, it stores the username and role in the constant and returns the .
Display Registered User in Route
You've rendered when accessing the route. Now, you'll display all registered users to that route.
:
Add Update and Delete Function to the Admin Route
You'll also display registered users to the admin route but add and functionality to the route:
:
Edit a User's Role
You'll create an event listener that will listen for a click on the button. When the button is clicked, you'll send a request to :
Delete Users
Deleting Users from the database should be the duty of an admin.
:
You've created an event listener that listens for a click on the button. When the button is clicked, you'll send a request to .
Please ensure the admin user is first on the list to avoid populating the database with an admin user again.
Logout Functionality
To log out users, you need to remove the token from the client and redirect the client to the home page.
You'll create a request to in the file:
The code snippet replaced the JWT token with an empty string and gave it a lifespan of 1 second.
After creating the request, add a logout button to the admin's route and user's route:
Node.js Authentication with LoginRadius
You can simply replace the many steps discussed above using LoginRadius. In turn, it helps you focus more on developing core application features while letting you quickly implement user signup and login and manager users.
In other words, LoginRadius is a SaaS-based customer identity and access management (CIAM) system with features to manage customer identity, privacy, and access. It is a simple, implementable solution for adding user authentication and authorization to your website.
Basically, LoginRadius handles user registration, login, and authentication. Other features of LoginRadius include:
-
Forms: LoginRadius can automatically pre-create registration and login forms for you.
-
Authentication and Authorization: It generates and sends a token to the user when login or signup is successful. Instead of using , you can use this token to authenticate users
-
Security: When using LoginRadius, you automatically have access to an admin console where you can control authentication factors, such as email, phone, and multi-factor auth for your Node.js app.
To get started with LoginRadius, you need to create an account with either the free plan or the Developer plan, customize your registration and login forms, and start managing your users.
How to Authenticate Your Node.js App with LoginRadius
This section briefly covers how authentication works with LoginRadius.
After signing up for LoginRadius, choose a name for your Node.js app.
After completing your LoginRadius signup process, you can get your App Name, API Key, and API Secret from the link on the sidebar. With these configurations, you can easily link the server-side of our application to LoginRadius.
LoginRadius automatically generates a link that will be used to authenticate users. This link contains the name of your LoginRadius application and a that authenticated users will be redirected to:
An instance of the link is given below:
Conclusion
You've successfully learned how to perform CRUD operations using MongoDB as a database, hash passwords, authenticate using JWT, and render Embedded JavaScript (EJS). You can put all these together to build more complex applications.
Resources
- A full, working version of the code used in this tutorial is available on GitHub
- Node.js Authentication with LoginRadius

Featured Posts
How to Implement JWT Authentication for CRUD APIs in Deno
Multi-Factor Authentication (MFA) with Redis Cache and OTP
Introduction to SolidJS
Build a Modern Login/Signup Form with Tailwind CSS and React
Implement HTTP Streaming with Node.js and Fetch API
NestJS: How to Implement Session-Based User Authentication
NestJS User Authentication with LoginRadius API
How to Authenticate Svelte Apps
Flutter Authentication: Implementing User Signup and Login
How to Secure Your LoopBack REST API with JWT Authentication
Node.js User Authentication Guide
Your Ultimate Guide to Next.js Authentication
Local Storage vs. Session Storage vs. Cookies
How to Secure a PHP API Using JWT
Using JWT Flask JWT Authentication- A Quick Guide
Build Your First Smart Contract with Ethereum & Solidity
What are JWT, JWS, JWE, JWK, and JWA?
How to Build an OpenCV Web App with Streamlit
32 React Best Practices That Every Programmer Should Follow
How to Build a Progressive Web App (PWA) with React
Bootstrap 4 vs. Bootstrap 5: What is the Difference?
JWT Authentication — Best Practices and When to Use
What Are Refresh Tokens? When & How to Use Them
How to Upgrade Your Vim Skills
How to Implement Role-Based Authentication with React Apps
How to Authenticate Users: JWT vs. Session
How to Use Azure Key Vault With an Azure Web App in C#
How to Implement Registration and Authentication in Django?
11 Tips for Managing Remote Software Engineering Teams
Implementing User Authentication in a Python Application
Add Authentication to Play Framework With OIDC and LoginRadius