Building Authentication API using Node , express and JWT .

Robert Rutenge
8 min readJan 6, 2020

In this tutorial , we will create a REST API from scratch using Nodejs and express , validate the data submitted and secure the endpoints via JSON Web Token (JWT) . We will also use MongoDB / Mongo Atlas to store our data .

The code for this tutorial can be found on github , see below ;-

https://github.com/robertrutenge/express-auth-api.git

Without further due , let’s get started as we have a lot of code to write . First thing first , you need to have node installed on your machine , create a project folder and open terminal then inside your project folder let’s fire up our app by initializing our node project .

npm init -y

Note : We have use -y to accept all default options

Let’s install expressjs

npm install express 

Now , let’s create index.js file on a root of our project as its our main entry point . Inside index.js file we will create a basic express app as below; —

Now let’s proceed , and run our app

node index.js

You should see a message Auth APIs listening on port 3000 on your console log . If you try to access the url , localhost:3000 now you should get Cannot GET / as no route has been created yet .

Let’s add start script inside package.json file so as we don’t have to launch our app every time by typing node index.js . remove the test script and add start script as below ;-

To avoid restarting our app everytime we make changes to it , we are going to use nodemon so as the refresh happens automatically . go on install nodemon as a dev dependency .

npm i -D nodemon

Modify the start script to use nodemon

Now let’s start our app , we should be good to go .

npm start

Now let’s start building by creating an endpoint for registration . Let’s start with the basic implementation ;-

As you can see on line 6 above , we have implemented a simple route for registration . Go on open postman and test going to localhost:3000/register and you should see Register returned as a response . That means so far so good .

Now for simplicity , we will collect 3 fields during regisrtation , namely person’s full name , email and password .

On the register route , lets change it to return our data by changing line 7 to

res.send(req.body)

Now , Let’s make that call on postman like below ;

If we make a call we can see it does not return anything , if you try to console.log req.body you will find that it’s undefined . This is because we need to add body parser middleware to have access to our req.body , let’s go ahead and do that .

Above our register route function add below code;

app.use(express.json());

The above basically tells express to recognize the incoming request object as JSON Object . Now if we run again our register endpoint , we should be able to get response .

Now that we can get our response , let’s take some time to add some validation on the data submitted . As of now if you send empty data or remove one of the fields , it should work fine .

We are going to use a package called joi for validation . Go on and install it .

npm install @hapi/joi

Then we will import in our main file and add validation as below :-

As seen above , from line 8 , we have created a schema and add validation rules for our fields . If you now try for example to submit password less than 6 characters you should get an error or submit invalid email .

Since when we get an error , we are sending the whole object as below

We will use object destructuring to get the error object , and then return 400 with the appropriate message which is under details . change the register route to below ; —

app.post(“/register”, (req, res) => {const { error } = registrationSchema.validate(req.body);if (error) return res.status(400).send(error.details[0].message);res.send(“Registered!”);});

If you run again , you will see 400 error with just a message , and if all validations have passed you will see “Registered!” message .

Now that we are done with validations , let’s go on and persist our data to the Database . As mentioned before , we are going to use MongoDB as our database , so go on to MongoDB Atlast , register or login .

Once login , click Build a new cluster on top right , choose a free tier with MO Sandbox which is free forever . Once everything is setup , go under the newly created cluster , and click connect , where you will have options on how to connect to your cluster as below ;-

Choose Connect Your Application , in which you will presented with connection string . Keep that connection string as we will use it in our application . And that’s it for Mongo Atlas .

Now to connect to MongoDB in our application , we will need to install a package called mongoose .

npm install mongoose

Now import mongoose and establish a connection

const mongoose = require(“mongoose”);mongoose.connect(“mongodb+srv://your_connection_string”,
{useNewUrlParser: true, useUnifiedTopology: true });

Once connected , let’s go and create our schema as below :-

const UserSchema = new mongoose.Schema({fullname: { type: String, required: true },email: { type: String, required: true },password: { type: String, required: true }});const User = mongoose.model(“user”, UserSchema);

Once our schema is set , we use mongoose.model() function to create our model as shown above .

Once our model is ready , the last step is to persist the data sent via post , see the update register route below :-

On the above , we have created an instance of our User model and then use the save method to persist the data . Note we have changed our function to async as we need to wait for some DB operations to end like persisting the date .

If you go on . and run the register endpoint on postman , you should be able to get a response with our newly persisted user object with an extra _id field . Also if you go to your cluster , then collections , you should see a newly created users collection with one document that has the data submitted .

Another thing before we start to login , we can see that the password is saved as plain text , we can change this by using a package called bcryptjs which will allow us to encrypt our password . go on and install it .

npm i bcryptjs

Let’s change the register function , and encrypt our password .

On line 4 , we are using salting to create a secure password . Now if you call the register endpoint again , the password should be encrypted .

One last thing , to ensure best practice , we will also check if email exists on registering as well as try and catch the model.save() just incase anything went goes wrong .

const emailExists = await User.findOne({ email: req.body.email });if (emailExists) return res.status(400).send(“Email already exists”);

Also

try {const savedUser = await user.save();res.send(savedUser);} catch (error) {res.status(400).send(error);}

Our final register route should be as below :

Now , let’s go and continue with login . To avoid this tutorial being too long as it’s already is , go ahead and validate the login credentials as its the same process we did with register .

I went along and added the login code as below , it should be straight forward :-

Now if email and password is correct , you are going to see “Logged In” message . Note that for the purpose of this tutorial , the email and password not correct messages are different but ideally and for security purpose they should be the same like “Email or password incorrect” .

Great ! now let’s finalize the last part for securing our endpoints . for this we are going to use a package called jsonwebtoken , let’s install it .

npm i jsonwebtoken

As usual , we will import it .

const jwt = require(“jsonwebtoken”);

From here , we are going to create a token when a user logs in using jwt.sign() method which accepts a payload as a first parameter and a secret key which ideally you will store it in your environment variables .

const token = jwt.sign({ _id: user._id, email: user.email },“YOUR_SECRET_KEY”);res.header(“auth_token”, token).send(token);

Now once logged in , we will add auth_token on response header so as it can be used to check authorization of various resources . Our Final login should look like below : —

One last thing before we call it off . Now that we have generate a token we need to learn how to secure our private routes .

We will secure our routes by creating a middleware which will first check if auth_token is present in our request and if not will throw 401 , unauthorized error . It will then use jwt.verify() method to verify the token and serve our request if passed . see below :-

Note . jwt.verify() will decrypt our token and give us a payload that we passed during the process of generating the token using jwt.sign() . If you have the token you can also decrypt it manually by going to https://jwt.io/ and paste your encoded token as below for my scenario .

Now , let’s use our middleware . We will create a simple get endpoint , let’s call it dashboard and it will contain very secure data that a user needs to be authenticated to access it .

app.get(“/dashboard”, (req, res) => {res.send(“VERY CONFIDENTIAL DATA”);});

If you run this on postman now , you should get “VERY CONFIDENTIAL DATA” . Now let’s go on and secure it . Its as simple as adding our middleware function on our get route .

app.get(“/dashboard”, tokenVerifier, (req, res) => {res.send(“VERY CONFIDENTIAL DATA”);});

Now if you run it on postman , you should get access denied message !

Go on postman and call login endpoint again , get the returned auth_token . Return back to dashboard endpoint , create auth_token header on postman with the generated token during login as its value and then call it again .

You can now see “VERY CONFIDENTIAL DATA” .

That’s it folks . Hope this helps you in one way or the other , don’t hesitate to reach out incase of any comments .

--

--

Robert Rutenge

Full-Stack Developer | ReactJS enthusiast | Problem Solver