Implement Authentication with Node.js using JWTs

Pranav Bakare - Sep 9 - - Dev Community

Here's a simple example of how to implement authentication with Node.js using JWTs (JSON Web Tokens). This example will cover:

  1. Registering a user.
  2. Logging in a user to get a JWT token.
  3. Protecting routes with the JWT token.

Step 1: Setup and Install Required Packages

Create a new Node.js project and install the following dependencies:

npm init -y
npm install express bcryptjs jsonwebtoken mongoose
Enter fullscreen mode Exit fullscreen mode
  • express: To set up the server and routes.
  • bcryptjs: To hash passwords.
  • jsonwebtoken: To sign and verify JWT tokens.
  • mongoose: To connect to MongoDB for storing user data.

Step 2: Create a Simple User Model with Mongoose

We'll use MongoDB to store user details. Set up the MongoDB connection and create a user model.

// models/User.js

const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');

const UserSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true
  },
  email: {
    type: String,
    required: true,
    unique: true
  },
  password: {
    type: String,
    required: true
  }
});

// Hash the password before saving
UserSchema.pre('save', async function (next) {
  if (!this.isModified('password')) return next();
  const salt = await bcrypt.genSalt(10);
  this.password = await bcrypt.hash(this.password, salt);
  next();
});

const User = mongoose.model('User', UserSchema);
module.exports = User;
Enter fullscreen mode Exit fullscreen mode

Step 3: Set Up the Server and Authentication Routes

Now, set up the Express server and create routes for registration, login, and a protected route.

// server.js

const express = require('express');
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const User = require('./models/User');
const app = express();

app.use(express.json());

// Connect to MongoDB
mongoose.connect('mongodb://localhost:27017/jwt-auth', {
  useNewUrlParser: true,
  useUnifiedTopology: true,
  useCreateIndex: true
}).then(() => console.log('MongoDB connected'));

// Secret for JWT signing
const JWT_SECRET = 'supersecretjwtkey';

// Register User
app.post('/register', async (req, res) => {
  const { name, email, password } = req.body;

  try {
    const user = new User({ name, email, password });
    await user.save();
    res.status(201).json({ message: 'User registered successfully!' });
  } catch (error) {
    res.status(400).json({ message: 'Error registering user' });
  }
});

// Login User and generate JWT
app.post('/login', async (req, res) => {
  const { email, password } = req.body;

  try {
    const user = await User.findOne({ email });
    if (!user) return res.status(400).json({ message: 'User not found' });

    const isMatch = await bcrypt.compare(password, user.password);
    if (!isMatch) return res.status(400).json({ message: 'Invalid credentials' });

    // Create and sign the JWT token
    const token = jwt.sign({ userId: user._id }, JWT_SECRET, { expiresIn: '1h' });

    res.json({ token });
  } catch (error) {
    res.status(500).json({ message: 'Server error' });
  }
});

// Middleware to protect routes
const authenticateJWT = (req, res, next) => {
  const token = req.header('Authorization')?.split(' ')[1];

  if (!token) return res.status(401).json({ message: 'No token, authorization denied' });

  try {
    const decoded = jwt.verify(token, JWT_SECRET);
    req.user = decoded.userId;
    next();
  } catch (err) {
    res.status(403).json({ message: 'Invalid token' });
  }
};

// Protected route
app.get('/protected', authenticateJWT, (req, res) => {
  res.json({ message: 'You have access to the protected route!', userId: req.user });
});

// Start the server
app.listen(5000, () => console.log('Server running on port 5000'));
Enter fullscreen mode Exit fullscreen mode

Step 4: Test the Application

You can now test the JWT authentication workflow using tools like Postman.

1. Register a User

  • URL: POST http://localhost:5000/register
  • Body (JSON):
  {
    "name": "John Doe",
    "email": "john@example.com",
    "password": "password123"
  }
Enter fullscreen mode Exit fullscreen mode

This will register the user in MongoDB with the hashed password.

2. Login to Get the JWT Token

  • URL: POST http://localhost:5000/login
  • Body (JSON):
  {
    "email": "john@example.com",
    "password": "password123"
  }
Enter fullscreen mode Exit fullscreen mode

The server will return a JWT token:

{
  "token": "your.jwt.token"
}
Enter fullscreen mode Exit fullscreen mode

3. Access the Protected Route

  • URL: GET http://localhost:5000/protected
  • Headers:
  Authorization: Bearer your.jwt.token
Enter fullscreen mode Exit fullscreen mode

If the token is valid, you will receive:

{
  "message": "You have access to the protected route!",
  "userId": "some-user-id"
}
Enter fullscreen mode Exit fullscreen mode

If the token is missing or invalid, you will get an error message.

Summary

  • User Registration: Users register with their name, email, and password, which is hashed and stored in the database.
  • User Login: The user logs in by sending their email and password. If valid, the server returns a JWT.
  • JWT Token: The JWT is stored on the client-side (usually in localStorage or cookies) and is sent with each request to protected routes.
  • Protected Routes: The server verifies the JWT token on each request to ensure the user is authenticated.

Let me know if you'd like help with any specific part of the JWT authentication process!

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