How to Build a Login/Register App with the MERN Stack (Part 3): Creating API Endpoints

In the previous part of this tutorial, How to Build a Login/Register App with the MERN Stack (Part 2): Setting Up the Database, we created a database and wrote some code that makes it much easier to use our database all over our app. In this part we will write code for our API endpoints, using Express, that we will use on client side.

Defining API Endpoints

Let’s create an entry point (file) for our Express app. I’ll call mine index.js. Now let’s define paths for the API endpoints.

Defining API endpoints - login register with MERN stack

Switch to your terminal and run npm run dev to start up this app. And as you can see, we now have a basic Express app listening on port 5000 if there is no environment variable called PORT. We did so because the deployment platform will use the PORT variable to specify which port the app should use.

NOTE: Do not forget to correctly set the name of the file that nodemon runs from the scripts section, specifically the dev script.

Setting Up Middleware

Before we continue working on our API endpoints, let’s first require and set up some middleware to help us complete the code for the API endpoints.

Middlewares - login register with MERN stack

On line 9 we create a new instance of the User class we wrote earlier to be able to use the register and login methods defined in it.

We create a new session store for the express-session middleware, on line 10, to make it able to communicate with the database.

On lines 12 and 13 we use body-parser to parse bodies of incoming requests and get data out of them.

On lines 15-20 we make use of the cors middleware to enable and control CORS. The origin option specifies which domains are allowed to use our API, later we will add the production URL to this list. And the credentials option sets the Access-Control-Allow-Credentials header to true, which allows the client to send cookies along with the request.

On lines 21-28we use the express-session middleware, and use the value of an environment variable, SESSION_KEY, as the secret to be used to sign the cookie. We also set the store option to be the one we created earlier on line 10.

NOTE: You should add these lines to the top of the index.js file. Do not forget to add SESSION_KEY to your .env file.

The ‘/api/users/register’ Endpoint

Register endpoint - login register with MERN stackThis endpoint is very simple. First, we extract the username, password, and email from the body of the incoming POST request. Then we use user.register() function, that takes in username, password, and email and returns an HTTP status code, to register that user. We store the returned HTTP status code in a variable called result. Finally, we send that status code back to the client.

The ‘/api/users/login’ Endpoint

Login endpoint - login register with MERN stackThis endpoint is a little bit similar to the ‘register‘ one. First, we extract the username and password from the request body. Then, we use user.login() function, that takes in username and password and returns an HTTP status code and a user object representing the authenticated user, to log the user in. Afterwards, we put the id, username, and email of authenticated use in a variable called loggedInUser. And if the status code is 204 we put that user in the session data, as shown on line 11. Finally, we send back a JSON response with the authenticated user data and status code.

The ‘/api/users/logout’ Endpoint

Logout endpoint - login register with MERN stackBecause we use sessions to identify logged in users, destroying the session of a client that makes request to the logout endpoint is enough to mark them as logged out. The sesssion.destroy() function takes in a callback to execute after destroying the session. In this case, we want to send a status code of 200 OK as response to the client.

The ‘/api/users/currentUser’ Endpoint

Current User endpoint

We will use this endpoint later, on client side, to know whether user is logged in or not. It simply sends back a JSON response containing logged in user data if there is a user in the session. If not, then it sends a JSON response with loggedIn set to false.

Custom Middleware

Now, we will make a couple of middleware, requireLoggedin  and requireNotLoggedin, to control who can access our endpoints.


Require Logged in middleware

We basically check to see if there is a user in the session, if not then we send back a 403 FORBIDDEN response. If there is a user, we continue on to the next handler by calling next(). BTW, I put these lines in a file called requireLoggedin.js in a folder called middlewares.


Require Not Logged in middleware.

This is basically the same as requireLoggedin. The only difference is that we flipped the if statement in this one.

Making Use of Them

Using custom middlewares.

After, bringing them in, we use them as middleware on our endpoints. We use requireNotLoggedin on '/api/users/register' and '/api/users/login' to prevent logged in users from using these endpoints. We also use requireLoggedin on '/api/users/logout' to prevent not logged in users from using this endpoint.


We used some external middleware to set up and secure our Express app. Then, we made some endpoints for our API, so that we can use them on client side to communicate with the server. Finally, we created and used our custom middleware to protect our API endpoints against misuse. In the next part (or two) we will work on frontend and client side using React.

NOTE: You can test your API using Postman. You can find all parts of this tutorial here and code here.


Related Posts