top of page
Writer's picturePushp Raj

A Comprehensive Guide to Implementing JWT



Meta Description: Fortify Your Web Apps with JWT in MERN Stack: A Step-by-Step Guide. Increase security and authentication. Keep Yourself Safe in the Digital Age


Security is a significant worry for web developers in today's digital world. As the number of online applications grows, it is critical to ensure the security of user data and authentication processes.


JSON Web Tokens (JWT) have developed a popular option for improving web application security. We will lead you through installing JWT to secure your online applications in this step-by-step guide successfully.


What exactly is JWT?


JWT (JSON Web Token) is a type of token. It is digitally signed, self-contained, and small in size. It provides a convenient data transport technique. JWT is not inherently secure, but its use can ensure the message's authenticity as long as the signature is checked and the payload's integrity is guaranteed. JWT is frequently used for stateless authentication in simple use cases involving non-complex systems.


Here's a JWT example:


eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6Im9sYXR1bmRlZ2FydWJhQGdtYWlsLmNvbSIsIm


JSON Web Token (JWT) is an open standard (RFC 7519) that offers a compact and self-contained method for securely communicating information as a JSON object between parties. Because it is digitally signed, this information can be checked and trusted.


The client will only need to use the credentials once to authenticate with the server. During this time, the server checks the credentials and returns a JSON Web Token (JWT) to the client.


The client can utilize this JSON Web Token (JWT) to authenticate itself to the server for all future queries, eliminating the need to submit credentials such as login and password.




JWT Workflow


The client sends a POST request with the username and password during the initial request. After successful authentication, the server generates a JWT and transmits it to the client.


This JWT may include a data payload. The client has this JWT token in the header of all subsequent requests. The server authenticates the user by using this token.


So the client does not need to transmit the user name and password to the server on each authentication request, but only once, after which the server issues a JWT to the client.


A JWT payload can include information such as a user ID so that when the client submits the JWT again, you can be confident that you issued it and see to whom it was sent.



JWT Structure


JWT is structured as follows: header.payload.signature


One thing to remember about JWT is that the information in the payload is exposed to everyone. As a result, we should not include sensitive information in the payload, such as passwords.


We can encrypt the payload data if we want to make it safer. We can, however, be certain that no one can tamper with or change the payload information. If you do this, the server will recognize it.


Pre-requisites:


Let's now authenticate and protect specific routes.

  • Basic HTML/JavaScript understanding is required.

  • Your machine should have NodeJS installed.

  • The express module is used to create the server.

  • Mongoose is a MongoDB connection and query module.

  • For hashing, use the crypt module.


You can use the following command to install all essential packages:


npm install express mongoose bcrypt --save


Steps for JWT Implementation


Now, let us look at the implementation of JWT in MERN Stack development. Let us look at it.


Step 1: First, build the following directory structure:

JWTApp


Step 2: Run the following command to install the "JSON web token" package.


npm install jsonwebtoken – save


Step 3: Develop the user model


Touch api/models/userModel.js to create a file called user userModel.js in the api/models folder.


Create a Mongoose schema in this file with the following properties:


  • fullName

  • email address

  • password

  • creation date

  • Insert the following code


'use strict;

var mongoose = require('mongoose'),

bcrypt = require('bcrypt'),

Schema = mongoose.Schema;

/**

* User Schema

*/

var UserSchema = new Schema({

fullName: {

type: String,

trim: true,

required: true

},

email: {

type: String,

unique: true,

lowercase: true,

trim: true,

required: true

},

hash_password: {

type: String

},

created: {

type: Date,

default: Date.now

}

});

UserSchema.methods.comparePassword = function(password) {

return bcrypt.compareSync(password, this.hash_password);

};

mongoose.model('User', UserSchema);


Step 4: Design the user handlers.


Create a file called user userController.js in the app/controllers folder by running touch api/controllers/userController.js.


Create three distinct handlers in the userController file using the code below.

'use strict;


var mongoose = require('mongoose'),

jwt = require('jsonwebtoken'),

bcrypt = require('bcrypt'),

User = mongoose.model('User');


exports.register = function(req, res) {

var newUser = new User(req.body);

newUser.hash_password = bcrypt.hashSync(req.body.password, 10);

newUser.save(function(err, user) {

if (err) {

return res.status(400).send({

message: err

});

} else {

user.hash_password = undefined;

return res.json(user);

}

});

};


exports.sign_in = function(req, res) {

User.findOne({

email: req.body.email

}, function(err, user) {

if (err) throw err;

if (!user || !user.comparePassword(req.body.password)) {

return res.status(401).json({ message: 'Authentication failed. Invalid user or password.' });

}

return res.json({ token: jwt.sign({ email: user.email, fullName: user.fullName, _id: user._id }, 'RESTFULAPIs') });

});

};


exports.loginRequired = function(req, res, next) {

if (req.user) {

next();

} else {


return res.status(401).json({ message: 'Unauthorized user!!' });

}

};

exports.profile = function(req, res, next) {

if (req.user) {

res.send(req.user);

next();

}

else {

return res.status(401).json({ message: 'Invalid token' });

}

};


Note: Using bcrypt, a hash password was preserved in the database.


Step 5: Create a file called user userRoute.js in the api/route folder and add the following code:

'use strict;


module.exports = function(app) {

var userHandlers = require('../controllers/userController.js');

// todoList Routes

app.route('/tasks')

.post(userHandlers.loginRequired, userHandlers.profile);

app.route('/auth/register')

.post(userHandlers.register);

app.route('/auth/sign_in')

.post(userHandlers.sign_in);

};


Step 6: Insert the following code into the server.js

'use strict;


var express = require('express'),

app = express(),

port = process.env.PORT || 3000,



User = require('./api/models/userModel'),

bodyParser = require('body-parser'),

jsonwebtoken = require("jsonwebtoken");


const mongoose = require('mongoose');

const option = {

socketTimeoutMS: 30000,

keepAlive: true,

reconnectTries: 30000

};


const mongoURI = process.env.MONGODB_URI;

mongoose.connect('mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb', option).then(function(){

//connected successfully

}, function(err) {

//err handle

});


app.use(bodyParser.urlencoded({ extended: true }));

app.use(bodyParser.json());


app.use(function(req, res, next) {

if (req.headers && req.headers.authorization && req.headers.authorization.split(' ')[0] === 'JWT') {

jsonwebtoken.verify(req.headers.authorization.split(' ')[1], 'RESTFULAPIs', function(err, decode) {

if (err) req.user = undefined;

req.user = decode;

next();

});

} else {

req.user = undefined;

next();

}

});

var routes = require('./api/routes/userRoutes');

routes(app);

app.use(function(req, res) {

res.status(404).send({ url: req.originalUrl + ' not found' })

});

app.listen(port);

console.log(' RESTful API server started on: ' + port);

module.exports = app;


Step 7: All you have to do is run the project with the following command and try logging in with the JWT.

npm start


Step 8: Launch Postman and send a post request to localhost:3000/auth/register.


Step 9: After that, sign in using the URL localhost:3000/auth/sign_in. Enter the email and password keys and values.


Add JWT and the token with a space between them under the value:


JWT eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6Im9sYXR1bmRlZ2FydWJhQGdtYWlsLmNvbSIsImZ1bGxOYW1lIjoiT2xhdHVuZGUgR2FydWJhIiwiX2lkIjoiNThmMjYzNDdiMTY1YzUxODM1NDMxYTNkIiwiaWF0IjoxNDkyMjgwMTk4fQ


Step 10: To get the profile, enter the key and value parameters. You want to make the following and transmit it. As we've seen, creating a JWT authentication system with NodeJS is relatively simple.


Adding Middleware to Protect Routes


Web developers face increasing hurdles in protecting their apps from security breaches and unauthorized access as the digital world evolves.


Middleware, a significant tool in web development, provides a dependable and practical approach to secure routes and sensitive data.


In this post, we will look at the concept of middleware and how it can be used to fortify the routes of your web application.


Middleware Fundamentals


Middleware in web development links the client and the server, processing requests and responses as they pass through the application. It stands between the request and response cycles of the application and can intercept, modify, or prevent incoming requests based on certain conditions.


Because middleware functions are executed sequentially, developers can design numerous layers of protection and conduct various tasks before a request reaches its intended path.


Middleware's Role in Route Protection


Route protection is a common application for middleware. It enables developers to specify access controls, authentication checks, and other security features for individual routes.


When a user tries to access a protected route, the middleware validates the request to ensure that only authorized users with sufficient permissions obtain access.


Implementing Route Protection Middleware


We present a simple step-by-step tutorial for installing route protection middleware in a Node.js and Express.js application below:


Step 1: Install and Configure Node.js and Express.js


Begin by making a new Node.js project and installing Express.js, a popular Node.js web application framework.


npm init -y

npm install express


Step 2: Specify the Middleware Function


Create a new JavaScript file, such as authMiddleware.js, in which you will define your unique route protection middleware function.


// authMiddleware.js

const authenticateUser = (req, res, next) => {

// Check if the user is authenticated

// Replace the following with your authentication logic

const isAuthenticated = true;


if (isAuthenticated) {

// If authenticated, proceed to the next middleware or route handler

next();

} else {

// If not authenticated, send an error response or redirect to a login page

res.status(401).json({ error: 'Unauthorized access' });

}

};

module.exports = authenticateUser;


Step 3: incorporate middleware into your application.


Import the custom middleware to secure particular routes in your main application file, such as app.js or index.js.


// app.js

const express = require('express');

const app = express();

const authenticateUser = require('./authMiddleware');


// Your route handlers go here

app.get('/', (req, res) => {

res.send('Welcome to the protected route!');

});


// Use the middleware to protect the route

app.get('/protected', authenticateUser, (req, res) => {

res.send('This is a protected route!');

});


// Start the server

app.listen(3000, () => {

console.log('Server is running on port 3000');

});


Adding Tokens to Authenticate Code


Token-based authentication is a mechanism in which users gain access to a web service or specified routes by submitting a unique token rather than standard credentials such as a username and password.


These tokens, often JSON Web Tokens (JWT), include encoded user information and are securely signed. When a user logs in, the server generates a token and delivers it to the client, who uses it in subsequent requests to access protected resources.


Implementation of Token-based Authentication


A basic step-by-step approach to creating token-based authentication in your web application is provided below:


Step 1: Select a Token Generation Library.


Choose a reliable and well-maintained token-generating library for your programming language and framework. Popular libraries include "jsonwebtoken" for Node.js and "PyJWT" for Python.


Step 2: Authentication of the User


Begin by configuring user authentication. Validate the user's credentials against the database or authentication source when they supply them during login.


Step 3: Create and distribute the token


If authentication is successful, create a token that contains necessary user information and a secret key for signing. In response to the login request, return this token to the client.


Step 4: Safely Store Tokens


When the client obtains the token, please keep it safe. Depending on your application's demands and security concerns, standard practices include employing HTTP-only cookies or local storage.


Step 5: Token Validation


The client should provide the token in the request headers for subsequent requests to protected routes. Using the secret key, validate the token's authenticity and integrity on the server side. This guarantees that the request comes from a legitimate user.


Step 6: Token Expiration and Renewal


To prevent indefinite access, give the tokens an expiration date. After the token expires, users must re-authenticate. Consider integrating token renewal or refresh tokens for a more smooth user experience.


Redirecting the Users after Login


When people successfully log in, they are often redirected to a dashboard or home page. In the MERN stack, you may accomplish this by utilizing the "react-router-dom" module, which provides sophisticated routing features for React applications.


Step 1: Install react-router-dom


Install "react-router-dom" in your React project first. Launch your terminal and type the following command:

npm install react-router-dom

Step 2: Enable User Login and Redirection.


Handle the login logic and save the user's authentication state in your login component. Redirect the user to the desired page after successful login using the "user history" hook from "react-router-dom."


// LoginForm.js

import React, { useState } from 'react';

import { useHistory } from 'react-router-dom';


const LoginForm = () => {

const [isLoggedIn, setIsLoggedIn] = useState(false);

const history = useHistory();


const handleLogin = () => {

// Perform login logic here


// Set the authentication status to actual upon successful login

setIsLoggedIn(true);


// Redirect the user to the dashboard or home page

history.push('/dashboard'); // Replace '/dashboard' with the desired URL

};


return (

<div>

{/* Login form code */}

<button onClick={handleLogin}>Login</button>

</div>

);

};

export default LoginForm;


Custom AuthMiddleware in MERN Stack: A Safeguard for Your Routes


AuthMiddleware acts as a bridge between incoming requests and the route handlers on the server. Before enabling access to protected routes, it intercepts each request and performs authentication checks.


The request is routed to its designated destination if a user is authenticated and authorized. Otherwise, the middleware can reject the request, redirect the user, or send an error response.


Follow these simple steps to implement custom AuthMiddleware in the MERN stack:


Step 1: Implementing Middleware Function


Define your custom AuthMiddleware method in your backend code (Express.js). This function should check the upcoming request's authentication state and access rights

// authMiddleware.js

const customAuthMiddleware = (req, res, next) => {

// Your authentication logic goes here

const isAuthenticated = true; // Replace with your authentication check


if (isAuthenticated) {

// If authenticated, proceed to the next middleware or route handler

next();

} else {

// If not authenticated, send an error response or redirect to a login page

res.status(401).json({ error: 'Unauthorized access' });

}

};

module.exports = customAuthMiddleware;


Step 2: Integrate the Middleware into the Routes


After that, incorporate your custom AuthMiddleware into the routes that require security. Import the AuthMiddleware into your Express.js application and apply it to the required routes.


// routes.js

const express = require('express');

const router = express.Router();

const customAuthMiddleware = require('./authMiddleware');


// Protected route example

router.get('/dashboard', customAuthMiddleware, (req, res) => {

// Your route handler logic for the dashboard

res.send('Welcome to the dashboard!');

});


// Unprotected route example

router.get('/public', (req, res) => {

res.send('This is a public route.');

});

module.exports = router;

Step 3: Integrate Middleware into Your Express App

Finally, apply the routes specified in the previous step to your main Express app file.

// app.js

const express = require('express');

const app = express();

const routes = require('./routes');


app.use('/api', routes); // Use your desired base path


// Your other Express configurations and middleware go here


app.listen(3000, () => {

console.log('Server is running on port 3000');

});


Custom Reflecting Token Expiration in MERN Stack: Keeping Your Users Safe


Token-based authentication is a popular way for securing MERN stack (MongoDB, Express.js, React, Node.js) applications. JSON Web Tokens (JWT) make handling user sessions and permissions. Simple, However, verifying token expiration is critical for security.


In this short and straightforward post, we'll look at how to reflect token expiration in the MERN stack, successfully protecting your application and users.


Understanding Token Expiration


The expiration of tokens is critical for preventing unauthorized access to protected channels. JWTs have a timestamp that defines their validity period. The token becomes invalid after this period, and the user must re-authenticate.


Step 1: Configuring the Token Expiration Time


During the token generation procedure in the MERN stack, you can customize the token expiration time. Set the expiration time when a user logs in or authenticates using the "expires" parameter.


// authController.js

const jwt = require('jsonwebtoken');


const generateToken = (user) => {

const secretKey = 'your-secret-key'; // Replace with your secret key

const expiresIn = '1h'; // Set the token expiration time (e.g., 1 hour)


// Create the token

const token = jwt.sign({ userId: user._id }, secretKey, { expiresIn });


return token;

};


module.exports = generateToken;


Step 2: Confirm Token Expiration


To block access after the token's validity period expires, you must verify its expiration on successive requests to protected routes.


// authMiddleware.js

const jwt = require('jsonwebtoken');


const customAuthMiddleware = (req, res, next) => {

const token = req.header('Authorization');


if (!token) {

return res.status(401).json({ error: 'Unauthorized access' });

}


// Verify the token and check for expiration

jwt.verify(token, 'your-secret-key', (err, decoded) => {

if (err) {

return res.status(401).json({ error: 'Token has expired' });

}


// If the token is valid, proceed to the next middleware or route handler

next();

});

};


module.exports = customAuthMiddleware;


Step 3: Refreshing Tokens


Consider creating a token refresh mechanism to improve user experience. Instead of asking consumers to reauthenticate after the token expires, generate a new token with a longer validity duration.


// authController.js

const jwt = require('jsonwebtoken');


const generateToken = (user) => {

const secretKey = 'your-secret-key'; // Replace with your secret key

const expiresIn = '1h'; // Set the token expiration time (e.g., 1 hour)

const refreshTokenExpiresIn = '7d'; // Set the refresh token expiration time (e.g., seven days)


// Create the token and refresh token

const token = jwt.sign({ userId: user._id }, secretKey, { expiresIn });

const refreshToken = jwt.sign({ userId: user._id }, secretKey, { expiresIn: refreshTokenExpiresIn });


return { token, refreshToken };

};


module.exports = generateToken;


Conclusion


JWT implementation can dramatically improve the security of your web apps. It is a popular choice among developers because of its simplicity, statelessness, and ability to offer secure data transmission.


You can implement this robust security mechanism into your web apps by following this step-by-step instruction and using a dependable JWT library. To keep your apps safe and resilient against potential threats, keep up to speed with best practices and security standards in your MERN stack learning journey.


Interesting F.A.Qs


Can AI affect MERN stack development?


The short answer is strict no; AI tools will never be able to replace MERN stack developers. While AI tools can help automate some operations, they cannot replace MERN stack developers' knowledge and experience.


Can the MERN stack be used in the healthcare industry?

Infomaze says MERN stack web developers, can create feature-rich web apps like electronic health records, medical imaging systems, and telemedicine platforms that can manage enormous amounts of data and real-time healthcare industry updates.

10 views

Related Posts

See All

Comments


Subscribe to Our Newsletter

Thanks for submitting!

bottom of page