Express.js JWT Authentication

Authentication keeps your application secure by verifying user identities. In Express.js, JSON Web Tokens (JWT) offer a simple and efficient way to handle this. JWTs are small, self-contained tokens that store user data and provide secure access to routes. This tutorial explains how to configure JWT authentication in Express.js, why it is important for security, and how to effectively implement it.



What is Express.js Authentication?

JWT authentication uses tokens to verify users. JWT is made up of three parts: header, payload, and signature, all separated by dots (for example, xxxxx.yyyyy.zzzzz). The header defines the token type and algorithm, the payload contains user data such as ID or role, and the signature ensures the integrity of the token. When a user logs in, your server generates a token and sends it to the client. The client then includes this token in requests to access protected resources. Express.js verifies the token to grant or deny access. This method is stateless, meaning no session data is stored on the server, making it lightweight and efficient.

How to Implement JWT Authentication in Express.js

You can add JWT authentication to your Express.js app in a few simple steps. Below, you'll find instructions and code snippets to guide you through the process.

Step 1: Set Up Your Project

To begin, create a new Node.js project and install the required packages. Open your terminal and run:

mkdir express-auth
cd express-auth
npm init -y
npm install express jsonwebtoken dotenv
  • express: Web framework for building the server.
  • jsonwebtoken: Generates and verifies JWT tokens.
  • dotenv: Manages environment variables.

Step 2: Configure Your Environment

Create a .env file in the root directory to store your secret key securely. Add this line:

JWT_SECRET=your-secret-key-here

Step 3: Build the Express Server

Create a file app.js and configure a basic Express server with JWT support. Here's the code:

require('dotenv').config(); // Load environment variables from .env file
const express = require('express'); // Import Express framework
const jwt = require('jsonwebtoken'); // Import JSON Web Token library

const app = express();
app.use(express.json()); // Middleware to parse JSON request bodies

const PORT = 3000; // Define the port for the server
const JWT_SECRET = process.env.JWT_SECRET; // Get JWT secret key from environment variables

// Sample user data (replace with a database in a production environment)
const users = [{ id: 1, username: 'alex', password: 'pass123' }];

// Login route to authenticate user and generate JWT token
app.post('/login', (req, res) => {
  const { username, password } = req.body;
  // Find user with matching username and password
  const user = users.find(u => u.username === username && u.password === password);

  if (!user) return res.status(401).json({ message: 'Invalid credentials' }); // Unauthorized response

  // Generate JWT token with user ID as payload, expires in 1 hour
  const token = jwt.sign({ id: user.id }, JWT_SECRET, { expiresIn: '1h' });
  res.json({ token }); // Send token in response
});

// Middleware to verify JWT and authenticate user
const authenticateToken = (req, res, next) => {
  const authHeader = req.headers['authorization']; // Get Authorization header
  const token = authHeader && authHeader.split(' ')[1]; // Extract token from 'Bearer TOKEN'

  if (!token) return res.status(401).json({ message: 'Token required' }); // Token missing

  // Verify JWT token
  jwt.verify(token, JWT_SECRET, (err, user) => {
    if (err) return res.status(403).json({ message: 'Invalid token' }); // Forbidden if token is invalid
    req.user = user; // Attach user data to request object
    next(); // Move to next middleware or route handler
  });
};

// Protected route that requires authentication
app.get('/profile', authenticateToken, (req, res) => {
  res.json({ message: 'Welcome, authenticated user!', userId: req.user.id });
});

// Start the server
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));

Step 4: Test the Implementation

Start your server with node app.js. Use a tool like Postman to test it:

  1. Send a POST request to http://localhost:3000/login with this body:
    { "username": "alex", "password": "pass123" }

    You'll receive a token in response:

    {"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwiaWF0IjoxNzQxNTA5MTM3LCJleHAiOjE3NDE1MTI3Mzd9.U5azSbv7CP3i45bj_TyEzxQQmQOB6qPt9D0DaOzje98"}
  2. Copy the token, then send a GET request to http://localhost:3000/profile. Add the token in the Authorization header Bearer <token> to access the secured route. You should see a success message with the user ID.
    {"message":"Welcome, authenticated user!","userId":1}

What is the Bearer Token

A Bearer token is an access token used in OAuth 2.0 and JWT to secure API requests. You include it in the Authorization header as:

Authorization: Bearer <token>

Here, <token> is an encoded credential string that grants access to resources. The term "Bearer" means that whoever holds the token can use it—no extra identity proof is needed as long as the token is valid.

How It Works

  1. After logging in, the authentication server issues the token.
  2. The token contains key details like user ID, expiration time, and a signature for verification.
  3. The client sends this token with API requests to access protected endpoints.
  4. The server verifies the token before granting access, ensuring secure and stateless communication.

This approach simplifies authentication while keeping your API interactions secure.

Conclusion

This tutorial has demonstrated the fundamental steps for implementing JWT authentication in Express.js. By generating and verifying tokens, you can effectively protect your application's routes and resources. With the knowledge gained here, you can now build more secure and reliable Node.js applications.



Found This Page Useful? Share It!
Get the Latest Tutorials and Updates
Join us on Telegram

Keep W3schools Growing with Your Support!
❤️ Support W3schools