Token-Based Authentication In Node.js Using JWT

Shashangka Shekhar Mandal   Source Code  Print 
10 Sep 2018
14 Sep 2018
Advanced
844

In this post we are going to learn about JSON Web Tokens (JWT), and know how to create a token by using JSON Web Tokens (JWT) on user authentication to secure NodeJS API’s. All we are going to creating a new sample application using Express-generator, then modify the application to create a token using JWT to verify user access for API’s. Let’s start the talk about getting an overview on authentication.

Authentication

Simply, we know that authentication is nothing but verifying the user identities for security purpose. Previously (old approach) we used server-based authentication where logged information stored in the server by creating a session for further identification. Think about those stored logged information which is going to match with the logged user for identity on each and every request to the server for serving data. This may cause performance issue while handling more authenticated response by the server.

Token-Based Authentication

Here comes token based authentication that means the server will response with a generated token on user login which will save in client instead of storing in the server to use for the further request. On each client request the token need to pass with the header which will verify in the server to serve data. The thought is much simpler, once you logged in just request with a valid token to get data on each request. Different types of NodeJS token-based authentication:

  • Passport

  • JSON Web Tokens (JWT)

  • Bcrypt

  • In our application we are going to use JWT to secure our API’s.

JSON Web Tokens (JWT)

According to JWT web site: “JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object.” Simply JSON Web Token (JWT) is encoded string to pass information between parties with secured way.

Following is JWT string sample:

“eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InNoYXNoYW5na2EiLCJwYXNzd29yZCI6IjEyMzQ1IiwiaWF0IjoxNTM2MjgwMjM1LCJleHAiOjE1MzYyODAyNjV9.iplar3jWiW8rh1gU1H6pYaPu6-njCfflrP8GLbx9Imw”
 

Which has three part separated by “.”, where the first part with purple color is header, then the part with blue color is payload, then the signature is with green color. While a user requesting for data to server this JWT string needs to pass with the header to verify in the server for user identification. Following screen demonstrate how JWT is going to work with client request.

So far we have learned about token-based authentication and get familiar with JWT. Now let’s see how to generate the JWT using a sample application in NodeJS, generated by Express-generator.

Let’s Code

As you can see from below screen the generated application with some simple steps using Express-generator. In case you need help please follow our previous post about getting started with Express and Express-generator. Open the application with Visual Code like below screen.

After installation package dependencies, time to run the application. Go to terminal tab in Visual Code then type “npm start” to start the application with predefined port 3000.

Open Postman to test the application by entering request URL “localhost:3000”. As you can see from the below screen our application is running fine at port 3000.

Let’s create a new route to user login. Go to visual code explorer to open “users.js” file then add below code snippet.

User Login

 /* Post users Login. */
 router.post('/login', function (req, res, next) {
 let userdata = {
 username: req.body.username,
 password: req.body.password
 };
 
 //Go to server for user varificarion
 if (userdata.username == "shashangka" && userdata.password == "12345") {
 res.status(200).json({
 message: 'Login Successful'
 });
 }
 else {
 res.status(401).json({
 message: 'Login Failed'
 });
 }
 });

This is where we are going to validate users for issuing the token which is going to pass with each request to the server. As you can see from below screen the login is successful while we are browsing with URL:https://localhost:3000/users/login.

We are good to go for next step with “jsonwebtoken” package installation. Type “npm install jsonwebtoken” then press enter to install the package to the application.

Open package.json to see the installed package.

Let’s create an object of JWT by including “jsonwebtoken” module to “users.js“ file using require() function.

 let jwt = require('jsonwebtoken');
 

Create Token

Here we are generating token using “jwt.sign() ”method, which have overload method as following definition.

  • jwt.sign(payload : string | Buffer | object, secret: Secret, [options]: SignOptions)

  • jwt.sign(payload : string | Buffer | object, secret: Secret, [callback: SignCallback])

  • jwt.sign(payload : string | Buffer | object, secret: Secret, [options: SignOptions, callback: SignCallback])

  • Options and callback function are optional. Let’s create a config file to store secret key and the hash algorithm for further use in token generation.

     module.exports = {
     secretKey: "Shashangka Shekhar",
     algorithm: 'HS256', //default: HS256
     };
    

    Here’s the list of Signature algorithm

  • HS256: HMAC using SHA-256 hash algorithm (default)

  • HS384: HMAC using SHA-384 hash algorithm

  • HS512: HMAC using SHA-512 hash algorithm

  • RS256: RSASSA using SHA-256 hash algorithm

  • RS384: RSASSA using SHA-384 hash algorithm

  • RS512: RSASSA using SHA-512 hash algorithm

  • ES256: ECDSA using P-256 curve and SHA-256 hash algorithm

  • ES384: ECDSA using P-384 curve and SHA-384 hash algorithm

  • ES512: ECDSA using P-521 curve and SHA-512 hash algorithm

  • none: No digital signature or MAC value included

  • Then register the module with the application in app.js.

 global.config = require('./config');

From following code snippet you may notice that, the first argument is passing user login data known as payload, then the second one is passing the secret key which is configured in config file. Lastly the optional parameter is passing object with token validity and encryption option.

 
 let token = jwt.sign(userdata, global.config.secretKey, {
 algorithm: global.config.algorithm,
 expiresIn: '1m'
 });

In response add new property “jwtoken” with return value of token string.

 res.status(200).json({
 message: 'Login Successful',
 jwtoken: token
 });

Finally Users Module

 var express = require('express');
 var router = express.Router();
 let jwt = require('jsonwebtoken');
 
 /* GET users listing. */
 router.get('/', function (req, res, next) {
 res.send('respond with a resource');
 });
 
 /* Post users Login. */
 router.post('/login', function (req, res, next) {
 let userdata = {
 username: req.body.username,
 password: req.body.password
 };
 
 //Go to server for user varificarion
 if (userdata.username == "shashangka" && userdata.password == "12345") {
 let token = jwt.sign(userdata, global.config.secretKey, {
 algorithm: global.config.algorithm,
 expiresIn: '1m'
 });
 
 res.status(200).json({
 message: 'Login Successful',
 jwtoken: token
 });
 }
 else {
 res.status(401).json({
 message: 'Login Failed'
 });
 }
 });
 
 module.exports = router;

Using postman browse with URL :https://localhost:3000/users/login. From the following screen as we can see the token is generated.

The generated token is valid for one minute you may configure it seven days by “7d” to increase the validity. Next, we are going to create a customer module which is going to handle the client request by verifying the bearer token to serve data. Create a new customers.js file by the following screenshot in visual code explorer.

Copy-paste below code to your newly created js file.

 var express = require('express');
 var router = express.Router();
 
 /* GET customers listing. */
 router.get('/', function (req, res, next) {
 res.send('respond with a resource');
 });
 
 module.exports = router;

Include the module in app.js file with below line of code.

 var customersRouter = require('./routes/customers');
 

Enable the route in app.js with following line of code.

 app.use('/customers', customersRouter);
 

Go to postman then enter request URLhttps://localhost:3000/customers. The newly created route is working fine as you can see from the below screenshot.

In this section we are going to verify the token using a middleware in router level. Let’s create another route to response client request that return with list of data.First let’s access the data without any authorization.

 /* GET customers listing without protection. */
 router.get('/data', function (req, res, next) {
 let customerdata = [
 {
 customerid: 1,
 customername: 'Mahfuz Bappy'
 },
 {
 customerid: 2,
 customername: 'Shamim Uddin'
 },
 {
 customerid: 3,
 customername: 'Ishani Isha'
 }
 ];
 
 res.json(customerdata);
 });

As you can see in postman while we are browsing by entering URL :https://localhost:3000/customers/data server is responding with list of data without any security validation, which is not secured that anyone can easily access data from server.

Here comes the middleware to verify the authorization to accessing server data. Let’s create a middleware named “verifytoken” in routes folder.

Accessing Token

Here we are going to access the token from request header by the key name “x-access-token”, which generated on user login.

 var express = require('express');
 var router = express.Router();
 
 router.use(function (req, res, next) {
 var token = req.headers['x-access-token'];
 console.log(token);
 
 });
 
 module.exports = router;

Copy-paste code snippet to newly created file then include it to customer.js by below line of code.

 let verifyToken = require('./verifytoken');
 

Pass the middleware as parameter like below line with existing route path.

 router.get('/data', verifyToken, function (req, res, next)
 

Verify Token

In this portion we are going to verify the accessed token for user authorization using “jwt.verify()” method.

Method Definition

  • jwt.verify(token: string, secret: Secret)

  • jwt.verify(token: string, secret: Secret, [options]: VerifyOptions)

  • jwt.verify(token: string, secret: Secret, [callback: VerifyCallback])

  • jwt.verify(token: string, secret: Secret, [options: VerifyOptions, callback: VerifyCallback])

  • Following code sample is to verify token. The first argument is the token string, then the next argument is secret key and the last one is the algorithm which used to decoding the token.

 jwt.verify(token, global.config.secretKey,
 {
 algorithm: global.config.algorithm
 
 }, function (err, decoded) {
 if (err) {
 let errordata = {
 message: err.message,
 expiredAt: err.expiredAt
 };
 console.log(errordata);
 return res.status(401).json({
 message: 'Unauthorized Access'
 });
 }
 req.decoded = decoded;
 console.log(decoded);
 next();
 });

Finally the Middleware

 var express = require('express');
 var router = express.Router();
 var jwt = require('jsonwebtoken');
 
 router.use(function (req, res, next) {
 var token = req.headers['x-access-token'];
 console.log(token);
 if (token) {
 jwt.verify(token, global.config.secretKey,
 {
 algorithm: global.config.algorithm
 
 }, function (err, decoded) {
 if (err) {
 let errordata = {
 message: err.message,
 expiredAt: err.expiredAt
 };
 console.log(errordata);
 return res.status(401).json({
 message: 'Unauthorized Access'
 });
 }
 req.decoded = decoded;
 console.log(decoded);
 next();
 });
 } else {
 return res.status(403).json({
 message: 'Forbidden Access'
 });
 }
 });
 
 module.exports = router;

Go to postman browse with URL :https://localhost:3000/users/login to regenerate the token by using valid login details.

Then enter URL :https://localhost:3000/customers/data pass generated token in header “x-access-token” by copying and paste it to value section. After that click on send button to send the request to server.

From the above screen, as you can see sever responded with return of JSON data after successful token verification. Here’s the console log in command terminal of visual code where token and payload information is printed on client request.

If the token is invalid or expired, server will response with message of “Unauthorized Access” instead of serving data.

As you can see from below screen the token expired message is printed in command terminal with the status code of 401.

That’s it, finally we know how to secure server request by token based authentication without storing any information

    Summary

    In this article, I have covered the following things:

  • About JSON Web Token (JWT)

  • Using JWT to secure ExpressJS API

  • Using router level middleware

  • Passing values within header with client request

  • Accessing passed value from header

Hope the article will help you to create secured APIs using Node and ExpressJS.

Hands-on Learning
+