logologo
  • AI Tools

    DB Query GeneratorMock InterviewResume BuilderLearning Path GeneratorCheatsheet GeneratorAgentic Prompt GeneratorCompany ResearchCover Letter Generator
  • XpertoAI
  • MVP Ready
  • Resources

    CertificationsTopicsExpertsCollectionsArticlesQuestionsVideosJobs
logologo

Elevate Your Coding with our comprehensive articles and niche collections.

Useful Links

  • Contact Us
  • Privacy Policy
  • Terms & Conditions
  • Refund & Cancellation
  • About Us

Resources

  • Xperto-AI
  • Certifications
  • Python
  • GenAI
  • Machine Learning

Interviews

  • DSA
  • System Design
  • Design Patterns
  • Frontend System Design
  • ReactJS

Procodebase © 2024. All rights reserved.

Level Up Your Skills with Xperto-AI

A multi-AI agent platform that helps you level up your development skills and ace your interview preparation to secure your dream job.

Launch Xperto-AI

Securing Your Node.js Application with JWT Authentication

author
Generated by
Abhishek Goyan

14/10/2024

Node.js

Sign in to read full article

In today's digital landscape, ensuring the security of your application is paramount, especially when dealing with user data. One method that has emerged as a robust solution for securing APIs is JSON Web Token (JWT) authentication. In this blog post, we will explore how to implement JWT authentication in a Node.js application as part of our CRUD app with MongoDB and TypeScript.

Understanding JWT

Before we jump into implementation, let’s clarify what JWT is. JSON Web Tokens are an open standard used to share security information between two parties. This transfer is compact, URL-safe, and can be verified and trusted since it is digitally signed.

A JWT consists of three parts:

  1. Header: Indicates the type of token and the signing algorithm being used (typically HMAC SHA256).
  2. Payload: Contains the claims, which are the information we want to store (typically user ID, roles, and other user-specific data).
  3. Signature: Ensures that the token is not altered. It is formed by combining the encoded header, encoded payload, and a secret key.

Let’s break that down further in the context of our CRUD application.

Setting Up Your Node.js Environment

To follow along, ensure you have Node.js installed, and you're working in a project set up with TypeScript. You can initialize your project with:

mkdir my-crud-app cd my-crud-app npm init -y npm install express mongoose jsonwebtoken bcryptjs dotenv npm install --save-dev typescript @types/node @types/express @types/mongoose @types/jsonwebtoken @types/bcryptjs

Also, don't forget to set up your tsconfig.json.

Identity Management: User Model

First, let’s create a user model. In your models directory, create a file named User.ts:

import mongoose, { Schema, Document } from 'mongoose'; export interface IUser extends Document { username: string; password: string; } const UserSchema: Schema = new Schema({ username: { type: String, required: true, unique: true }, password: { type: String, required: true } }); export const User = mongoose.model<IUser>('User', UserSchema);

In our user model, we are defining a simple schema that consists of a username and password.

Registering a User

Now we need to create a route to register users. Create a file named auth.ts in your routes directory:

import express from 'express'; import bcrypt from 'bcryptjs'; import { User } from '../models/User'; import jwt from 'jsonwebtoken'; const router = express.Router(); router.post('/register', async (req, res) => { try { const { username, password } = req.body; // Check if user already exists const existingUser = await User.findOne({ username }); if (existingUser) { return res.status(400).json({ message: 'User already exists' }); } const hashedPassword = await bcrypt.hash(password, 10); const user = new User({ username, password: hashedPassword }); await user.save(); // Generate JWT token const token = jwt.sign({ id: user._id }, process.env.JWT_SECRET || 'your_secret', { expiresIn: '1h' }); res.status(201).json({ token }); } catch (error) { res.status(500).json({ message: 'Server error' }); } }); export default router;

Explanation

  • We import necessary packages like bcryptjs for hashing passwords and jsonwebtoken for creating JWTs.
  • We create a new user after checking if the user already exists.
  • Upon successful registration, we return a JWT token, which can be used for subsequent requests.

Authenticating a User

Next, let’s create a route to authenticate a user. We’ll extend our auth.ts file:

router.post('/login', async (req, res) => { const { username, password } = req.body; const user = await User.findOne({ username }); if (!user || !(await bcrypt.compare(password, user.password))) { return res.status(401).json({ message: 'Invalid credentials' }); } const token = jwt.sign({ id: user._id }, process.env.JWT_SECRET || 'your_secret', { expiresIn: '1h' }); res.json({ token }); });

Explanation

  • In the login route, we check the user's credentials against the database and compare the hash with the provided password.
  • If valid, we generate a JWT token and send it back to the client.

Protecting Routes with JWT Middleware

Now, we need to protect certain routes. Create a middleware function that verifies the JWT token:

import { Request, Response, NextFunction } from 'express'; import jwt from 'jsonwebtoken'; export const verifyToken = (req: Request, res: Response, next: NextFunction) => { const token = req.headers['authorization']?.split(' ')[1]; if (!token) { return res.status(403).json({ message: 'Access denied' }); } jwt.verify(token, process.env.JWT_SECRET || 'your_secret', (err, decoded) => { if (err) { return res.status(401).json({ message: 'Invalid token' }); } // Add user information to the request for further usage req.user = decoded; next(); }); };

Explanation

  • This middleware checks for the JWT in the Authorization header.
  • If valid, it adds the decoded user information to the request object for further use in subsequent middleware or route handlers.

Example: Securing a Protected Route

Let’s create a protected route for retrieving user information in your routes directory:

router.get('/user', verifyToken, (req, res) => { res.json({ id: req.user.id, username: req.user.username }); });

Explanation

  • This route uses the verifyToken middleware to ensure only authenticated users can access it. If the token is valid, the user’s information is sent back.

Final Steps

To complete the implementation, don’t forget to initialize your Express app and connect to MongoDB:

import express from 'express'; import mongoose from 'mongoose'; import dotenv from 'dotenv'; import authRoutes from './routes/auth'; dotenv.config(); const app = express(); app.use(express.json()); mongoose.connect(process.env.MONGODB_URI || 'your_mongodb_uri', { useNewUrlParser: true, useUnifiedTopology: true }) .then(() => console.log('MongoDB connected')) .catch(err => console.log(err)); app.use('/auth', authRoutes); app.listen(5000, () => console.log('Server running on port 5000'));

Explanation

  • We set up the Express app, connect to MongoDB, and include our authentication routes to handle registration and login.

Implementing JWT authentication not only secures your application but also creates a scalable and practical way of managing user sessions. With this framework, you can further enhance your CRUD application with secure access controls and protect your user data effectively.

Popular Tags

Node.jsJWTAuthentication

Share now!

Like & Bookmark!

Related Collections

  • Build a CRUD App with Node.js, MongoDB, and TypeScript

    14/10/2024 | NodeJS

  • Optimising Backend APIs - Node.js

    31/08/2024 | NodeJS

  • Node.js Mastery: From Foundations to Frontiers

    08/10/2024 | NodeJS

Related Articles

  • Creating a Basic Node.js Application with TypeScript

    14/10/2024 | NodeJS

  • Implementing CRUD Operations in Node.js with MongoDB and TypeScript

    14/10/2024 | NodeJS

  • Understanding Concurrency and Asynchronous Processing in Node.js

    31/08/2024 | NodeJS

  • Exploring Streams in Node.js

    23/07/2024 | NodeJS

  • Deploying Your Node.js Application

    14/10/2024 | NodeJS

  • Caching Strategies in Node.js: Enhancing Performance and Speed

    31/08/2024 | NodeJS

  • Introduction to Node.js, MongoDB, and TypeScript

    14/10/2024 | NodeJS

Popular Category

  • Python
  • Generative AI
  • Machine Learning
  • ReactJS
  • System Design