Secure Your ExpressJS & ReactJS App: User Authentication with JWT

Secure Your ExpressJS & ReactJS App: User Authentication with JWT

A Step-by-Step Guide for Implementing Secure Logins

User authentication is an essential component of every modern Web application. It enables you to restrict access to specific features and data based on a user's login state. This tutorial will walk you through creating user authentication with JSON Web Tokens (JWT) in an ExpressJS backend and a ReactJS frontend.

What is JWT?

JWT is a simple and self-contained method of securely exchanging data between parties. It is composed of three parts:

  • Header: The header contains the token type (JWT) and the signature algorithm.

  • Payload: Encodes user information such as user ID, username, and roles. This data can be customised to meet the specific requirements of your application.

  • Signature: The signature ensures the token's integrity by employing a secret key known only to the server.

Setting up the Backend (ExpressJS)

  1. Dependencies: Install express, jsonwebtoken, and a database library (e.g., Mongoose) for storing user data.

  2. User Model: Create a user model for your database that includes fields such as username, password (hashed for security), and other pertinent information.

  3. Registration Route: Create a route for user registration. Hash the user's password before putting it in the database.

  4. Login Route: Create a login route. Validate the user's credentials against the database. If valid, create a JWT with the user ID or any necessary information. Sign the token using a secret key stored securely in an environment variable.

  5. Protected Routes: Use middleware to secure certain routes. This middleware checks for a valid JWT in the request's permission header. If the token is genuine, the request proceeds; otherwise, an error response is provided.

Here's an example of a protected route in ExpressJS:

const express = require('express');
const jwt = require('jsonwebtoken');

const router = express.Router();

// Protected route
router.get('/protected', verifyJWT, (req, res) => {
  // Access user data from decoded token (req.user)
  res.json({ message: 'Welcome, authorized user!' });
});

// Middleware to verify the JWT token
function verifyJWT(req, res, next) {
  const token = req.headers.authorization.split(' ')[1];
  if (!token) return res.status(401).json({ message: 'Unauthorized' });

  jwt.verify(token, process.env.JWT_SECRET, (err, decoded) => {
    if (err) return res.status(403).json({ message: 'Forbidden' });
    req.user = decoded;
    next();
  });
}

module.exports = router;

Securing the Frontend (ReactJS)

  1. Login Functionality: In ReactJS, create a login form that sends user credentials to the backend login route.

  2. Storing JWT: After successful login, save the received JWT in local storage or a secure cookie (whichever you prefer).

  3. Authorization Headers: When sending requests to protected routes, include the JWT in the authorization header. To handle authorization headers, you can use frameworks like Axios.

    Here's an example of adding the JWT to an Axios request:

     import axios from 'axios';
    
     const token = localStorage.getItem('jwtToken');
    
     axios.get('/protected', {
       headers: {
         Authorization: `Bearer ${token}`,
       },
     })
     .then(response => {
       // Handle response
     })
     .catch(error => {
       // Handle error
     });
    
  4. Handling Expired Tokens: On the frontend, implement functionality to handle expired JWTs. Before making any queries, you can check the token's expiration time and refresh it as needed.

Conclusion

JWT offers a secure and effective method for implementing user authentication in your online application. By following these instructions and knowing the fundamentals of JWT, you can build a strong authentication mechanism for your ExpressJS and ReactJS applications.