Master Authentication in Node.js with Json Web Tokens (JWT)


 

In your routine work you login to several websites in a day using the unique username and password with which you have created an account to login into the website. It is these unique credentials that ensure security of your data related to you on the websites. But additional layer of security is a must and thus JWT can help in authentication, authorization and secure information exchange.     

Authentication is crucial in web applications as it needs to be ensured that only authenticated users can access the resources on the application. JWT ensures strong authentication as the ID token returned to the client is unique to each user when he/she login into the application. Also, JWT ensures security of information transmitting between the parties as you are certain that information is actually coming from a trusted party which is supposed to send it.

Now lets understand what exactly is JWT. JWT is a encoded string of characters that is generated using a secret key. This encrypted string of characters ensures information security and is only accessible by the party which holds the secret key with which it was encrypted.

Lets understand through a real-world scenario. You go to a website (we call it client) and sign in using a username and password. The client sends a request to the server with these username and password. At the server side, these username and password is checked and if they are valid then a JWT token is created using a secret key. This token is sent back to the client. Now, whenever the client again sends the request then this token must be send along with it by adding it in request header. JWT token contains encrypted information pertaining to user level access like expiration date and to which resources the user has access etc.  

 But have you ever wondered the complexities that goes behind the authorization process. Lets dig deeper by getting our hands on code! But before proceeding with writing the code, you must be knowing about how to create REST API using node.js. You can go through various tutorials before moving ahead with learning user authentication with JWT.

Setting up the environment

Before coding, we need to setup the environment. You need to create a node.js project by running the following command.

npm init

You need to install following dependencies first in the folder where all your source code will be saved. Run the below command in the command prompt.

npm install bcryptjs body-parser express jsonwebtoken mongoose

After all the dependencies are installed you need to setup the database and provide all the details in db.js file.

Configuring the Database

To configure the database, we will use mongodb as the database. For that login to cloud.mongodb.com then create a cluster. When the cluster is created, then connect with the cluster by selecting the Connect button. Then select Connect to your Application and copy the connection string url that we will use to connect with our database. The connection string will look something like this as shown below which we have to add in our application code:

mongodb+srv://<username>:<password>@cluster0.kjdhwak.mongodb.net/?retryWrites=true&w=majority

Replace the <username> and <password> with the username and password which you have put for your cluster. Put the below code in db.js.

const mongoose = require('mongoose');

// the URI Connection String to connect to mongodb cluster running on cloud. If do not use //database name in the connection string, mongodb will create a new database for you. Here we //define a connectionURL to contains the connection string.

var connectionUrl = 'mongodb+srv://nikhil:<password>@cluster0.kjdhwak.mongodb.net/?retryWrites=true&w=majority';

//this function establishes a connection between node.js app and mongodb database running online on cloud

//useNewUrlParser: You can set it True to use the new MongoDB connection string parser.

//useUnifiedTopology: You can set it True to use the new Server Discovery and Monitoring engine

var conn = mongoose.connect(

  connectionUrl,

  { useNewUrlParser: true, useUnifiedTopology: true },

  (err) => {

    if (err) throw err;

    console.log('Connected to Database!');

  }

);

module.exports = conn;

 

Defining the authorization and authentication route for the users

Once you define the database structure for your application, we need to focus on defining the structure of authorizing the users. Here we will define how the users will be authorized and allowed to login in the application.

We also need to define the authorization structure for the application wherein we will define to which resources the users will have access.

You need to create a user schema in the Users.js file. Create a ‘user’ folder and paste the below code in that. Through user schema you can define the blueprint to create user models and what properties it should include like name, email, password etc.

var mongoose = require('mongoose');  

var UserSchema = new mongoose.Schema({  

  name: String,

  email: String,

  password: String

});

mongoose.model('User', UserSchema);

module.exports = mongoose.model('User');


Then lets first create a .env file in the our project in VS Code to hold the secret key which will be used to create the JWT token. Please note that this secret key is very important and you need to keep it confidential at all times. This secret key should not be visible to public at any time.

SECRET_KEY=’ABCEFGHIJKLMNOPQRSTUVWXYZ’

Now, lets start building the authentication logic!

For this add a folder named ‘authorization’ and create a file named ‘authController.js’ under it. Add below code in this file.

const express = require('express');

const router = express.Router();

//create a body parser middle ware

var bodyParser = require('body-parser');

// the body parser is then used to populate the req.body with the inputs that the request

router.use(bodyParser.urlencoded({ extended: false }));

router.use(bodyParser.json());

var User = require('../user/User');

 

Now, once you are done with this, lets dive into the process of creating the JWT. For that you need to add the modules jwtwebtoken and bcryptjs. Add the below code into the authController.js file.

var jwt = require('jsonwebtoken');

var bcrypt = require('bcryptjs');

var SECRET_KEY = process.env.SECRET_KEY;

 

Run the below command after opening the terminal.

npm install jsonwebtoken bcryptjs –save

Till this point, we followed all steps that are necessary for authentication.

Now we will create a /register endpoint where we will register the user, create a JWT token.

router.post('/register', function(req, res) {

 

    var hashedPassword = bcrypt.hashSync(req.body.password, 8);

   

    User.create({

      name : req.body.name,

      email : req.body.email,

      password : hashedPassword

    },

    function (err, user) {

      if (err) return res.status(500).send("There was a problem registering the user.")

      // create a token

      var token = jwt.sign({ id: user._id }, SECRET_KEY, {

        expiresIn: 86400 // expires in 24 hours

      });

      res.status(200).send({ auth: true, token: token });

    });

  });

 

The user is asked to submit three items in this case: a name, an email address, and a password. We're going to use Bcrypt's hashing algorithm to quickly encrypt the password. Next, make a new user by using the hashed password along with a name and email. We can easily produce a token for that user once it has been successfully created.

A payload and the secret key are the only parameters required by the jwt.sign() method. It produces a distinctive string of characters that serves as the payload. In this instance, the payload is an object that merely contains the user's id. Let's create some code that uses the token we received from the register endpoint to obtain the user id.

Now, below is the code to get the user id from the token that we received from the request body. Add this code in authController.js.

router.get('/person', function(req, res) {

  var token = req.headers['x-access-token'];

  if (!token) return res.status(401).send({ auth: false, message: 'Token not provided.' });

  jwt.verify(token, config.secret, function(err, decoded) {

    if (err) return res.status(500).send({ auth: false, message: 'Token authentication failed!' });

    res.status(200).send(decoded);

  });

});

module.export = router;

you need to add a reference to the controller in app.js.

//app.js

var authController = require('./authorization/authController');

app.use('/api/auth', authController);

module.exports = app;

 

Now go back to the terminal in VS Code project then change the directory to where your actual code resides and then type below command:

node server.js

If things move smoothly and there are no bugs (which are integral part of developer’s life) you are able to connect to the database!

Till that time happy coding!

 

 

 

 

 

 

 

 

 

 

Post a Comment

0 Comments