Saturday, September 21, 2019

implement JWT Authentication token With Web API in nodejs

In nodejs JWT token is the most popular to identify authorized users and session management Token-based security.

JSON Web Token (JWT) is the approach of securely transmitting data for authentication and authorization. JWT made with three parts: Header, Payloads, and Signature.

By using this token main benefit is that there is no alteration of data form generated token.

Here we will discuss how to implement JSON Web Token (JWT) in nodeJS with expressJS and mongoose for MongoDB and how to pass Authorization Bearer token form front-end side.

Before start install NPM modules by using following commands where package.json available
npm install express-jwt --save
npm install jsonwebtoken --save

EX: middleware.js
.....
.....
....
const expressJWT = require("express-jwt");

//This is a global variables which can access any files
global.JWT_TOKEN_ALLOW_ACCESS = {};
global.JWT_TOKEN_KEY = "my any secret key"; // here you can write any secred key like as "dsffsd", "myToken123"
.....
....
....
module.exports = app => {
    ....
    ....
    ....

     * JWT authentication
     */
    global.JWT_TOKEN_ALLOW_ACCESS = expressJWT({
        secret: global.JWT_TOKEN_KEY,
        userProperty: 'payload'
    });
    .....
    .....
    .....
    return app;
};

Here, middleware is the where we can configure express-jwt secrete key and initialize expressJWT. you may have config.js, router.js

userModel.js
/**
 * @Purpose : User model
 */
var mongoose = require('mongoose'),
        Schema = mongoose.Schema,
        ObjectId = Schema.ObjectId,
        jwt = require("jsonwebtoken");

var userSchema = new Schema({
    profile_id: {
        type: Schema.Types.ObjectId,
        ref: 'UserProfile',
        index: true
    },
    profile_image_id: {
        type: Schema.Types.ObjectId,
        ref: 'Photo',
        index: true
    },
    first_name: {
        type: String,
        index: true
    },
    last_name: {
        type: String,
        index: true
    },
    gender: {
        type: String,
        enum: ['Male', 'Female'],
        //default: "Male",
        index: true
    },
    email: {
        type: String,
        //unique: true
    },
    password: {
        type: String,
        //select: true
    },
    user_type: {
        type: Number,
        index: true
    },
    is_active: {
        type: Number,
        default: -1,
        index: true
    },
}, {collection: 'user'});

/**
 *Validations and methods
 */
....
....
....
....

userSchema.methods.generateJWT = function (user) {
    return jwt.sign({
        id: user._id,
        username: user.nick_name,
        firstname: user.first_name,
        lastname: user.last_name,
        email: user.email,
        gender: user.gender,
        user_type: user.user_type
    }, global.JWT_TOKEN_KEY, {
        expiresIn: '365d' //365 days
    });
};

....
....
....

var User = module.exports = mongoose.model("User", userSchema);

Here, we use jwt = require("jsonwebtoken"); for sign jwt token and need to give secret key which is given in middleware.js so we had use global.JWT_TOKEN_KEY.

This method will call from login/authentication api/controller/routing after successfully login, call this method to sign/create jwt token.

authCtrl.js
...
...
...
/**
 * @description login action
 */
AuthCtrl.login = (req, res) => {
    ...
    ...
    ...
    ...
    //After successfully login call method generateJWT before sending API response to front-end

    console.log(user); // user is the object which have a data by UserModel.find({...}); query

    var accessToken = user.generateJWT(user);
    res.cookie('my-app-token', accessToken, {maxAge: global.hzConfig.jwtTimeOut, httpOnly: false});
    res.status(200).json({
        status: 1,
        type: "success",
        message: 'Login successfull...',
        data: {
            ....
            ....
            ....
            nick_name: user.nick_name,
            token : accessToken
        }
    });
};

This token you can store in a cookie or local storage in front-end side. Here, we have use res.cookie so it will store in cookie automatically by given name my-app-token in front-end side in the web browser, but if you are using any application which is not using cookie then you can store it in session storage or local storage which will available in response's token property.

For add this authentication token in API, you can put global.JWT_TOKEN_ALLOW_ACCESS as middleware in API like as bellow.

post.js
const express = require("express");
const router = express.Router();
const PostCtrl = require("../../../services/security/postCtrl");

/**
 * @description Post routes
 * @example http://localhost:3000/v1/post/'Route name'
 */

...
...
...

//Create post API : http://localhost:3000/v1/post/create
router.route("/create").post(global.JWT_TOKEN_ALLOW_ACCESS, PostCtrl.create);

//Update post API : http://localhost:3000/v1/post/update
router.route("/update").post(global.JWT_TOKEN_ALLOW_ACCESS, PostCtrl.update);

//Get posts API : http://localhost:3000/v1/post/get-post-list
router.route("/get-post-list").get(global.JWT_TOKEN_ALLOW_ACCESS, PostCtrl.getPostList);

...
...
...

module.exports = router;

By adding global.JWT_TOKEN_ALLOW_ACCESS with an api as middleware, if user access without passing token it will throw 401 unauthorized error.

for display login user's information

postCtrl.js
...
...
...

PostCtrl.getPostList = (req, res) => {
    console.log(req.payload); // here you can get all information which is store at jwt.sign as a login user's session
    ...
    ...
    ...
};

...
...
...

module.exports = PostCtrl;

After these process, you must have to pass Authorization in the header of an HTTP request from front-end side in which routing you had put in server-side. authentication with Bearer token need to pass like as bellow

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjU3NjI3ZmRlNGQ3YzNmY2MwYTY5MDQ5NiIsImxpbmtfaWQiOiJsYXhtYW4iLCJpc19vbmxpbmUiOjEsInVzZXJuYW1lIjoibGF4bWFuIiwiZmlyc3RuYW1lIjoiQ2hhdmRhIiwibGFzdG5hbWUiOiJMYXhtYW4iLCJlbWFpbCI6ImxheG1hbkBzaWxpY29uaW5mby5jb20iLCJnZW5kZXIiOiJNYWxlIiwiZGVmYXVsdF9pbWFnZSI6Im5vX8VzZXJfbWFsZV80LnN2ZyIsImltYWdlIjoicHJvZmlsZV8xMTU1NjE4NDA3MzY5NC5qcGciLCJyb2xlIjoidXNlciIsImlhdCI6MTU2OTA0ODc5NSwiZXhwIjoxNjAwNTg0Nzk1fQ.BAjqkK9HQxIIEIZg_F9i7ZZ74fZ-VHCdBBn6P44UwAg

For more details about how to pass Authorization Bearer token from front-end side check bellow link

https://laxmanchavda.blogspot.com/2018/10/intercept-all-http-request-in-angular.html
OR
https://laxmanchavda.blogspot.com/2018/01/intercept-all-ajax-request-in-jquery.html

From this demo, you can implement this JSON Web Token (JWT) in nodejs app very easily.

1 comment: