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.
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
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.
9 we create a new instance of the
User class we wrote earlier to be able to use the
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.
13 we use
body-parser to parse bodies of incoming requests and get data out of them.
15-20 we make use of the
cors middleware to enable and control
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.
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
NOTE: You should add these lines to the top of the
index.js file. Do not forget to add
SESSION_KEY to your
The ‘/api/users/register’ Endpoint
This 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
This 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
Because 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
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
Now, we will make a couple of middleware,
requireNotLoggedin, to control who can access our endpoints.
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
This is basically the same as
requireLoggedin. The only difference is that we flipped the
if statement in this one.
Making Use of Them
After, bringing them in, we use them as middleware on our endpoints. We use
'/api/users/login' to prevent logged in users from using these endpoints. We also use
'/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.