JWT Authentication With NodeJS

Create a Custom Authentication System with Node.js and JWT

Authentication is essential for modern web applications. In this tutorial, we’ll build a custom authentication system using Node.js, JWT, and React. You’ll learn how to set up secure…


This content originally appeared on DEV Community and was authored by Pedro Henrique Machado

Create a Custom Authentication System with Node.js and JWT

Authentication is essential for modern web applications. In this tutorial, we’ll build a custom authentication system using Node.js, JWT, and React. You'll learn how to set up secure user registration and login, manage authentication states, and handle token expiration with refresh tokens.

Prerequisites

Before starting, ensure you have:

  • Node.js installed on your system.
  • Basic understanding of React, Node.js, and JavaScript.
  • A code editor like VS Code.

Step 1: Set Up the Backend

Start by creating the backend for handling user authentication.

1.1 Initialize the Project

mkdir node-jwt-auth
cd node-jwt-auth
npm init -y

1.2 Install Required Libraries

npm install express jsonwebtoken bcrypt cors

Step 2: Implement the Backend

2.1 Create the Server

Create a file named server.js in the project root:

const express = require("express");
const jwt = require("jsonwebtoken");
const bcrypt = require("bcrypt");
const cors = require("cors");

const app = express();
app.use(express.json()); // Built-in middleware to parse JSON requests
app.use(cors());

// Mock user database
const users = [];

// JWT secret keys
const ACCESS_TOKEN_SECRET = "your_access_token_secret";
const REFRESH_TOKEN_SECRET = "your_refresh_token_secret";

// Refresh token storage
let refreshTokens = [];

// User registration endpoint
app.post("/register", async (req, res) => {
  const { username, password } = req.body;

  // Check if user already exists
  if (users.find((user) => user.username === username)) {
    return res.status(400).json({ error: "User already exists" });
  }

  // Hash the password
  const hashedPassword = await bcrypt.hash(password, 10);

  // Save user
  users.push({ username, password: hashedPassword });
  res.status(201).json({ message: "User registered successfully" });
});

// User login endpoint
app.post("/login", async (req, res) => {
  const { username, password } = req.body;

  // Find user
  const user = users.find((user) => user.username === username);
  if (!user || !(await bcrypt.compare(password, user.password))) {
    return res.status(400).json({ error: "Invalid username or password" });
  }

  // Generate tokens
  const accessToken = jwt.sign({ username }, ACCESS_TOKEN_SECRET, {
    expiresIn: "15m",
  });
  const refreshToken = jwt.sign({ username }, REFRESH_TOKEN_SECRET);

  refreshTokens.push(refreshToken); // Store refresh token
  res.json({ accessToken, refreshToken });
});

// Refresh token endpoint
app.post("/token", (req, res) => {
  const { token } = req.body;
  if (!token || !refreshTokens.includes(token)) {
    return res.status(403).json({ error: "Invalid refresh token" });
  }

  try {
    const user = jwt.verify(token, REFRESH_TOKEN_SECRET);
    const accessToken = jwt.sign(
      { username: user.username },
      ACCESS_TOKEN_SECRET,
      {
        expiresIn: "15m",
      }
    );
    res.json({ accessToken });
  } catch {
    res.status(403).json({ error: "Invalid token" });
  }
});

// Logout endpoint
app.post("/logout", (req, res) => {
  const { token } = req.body;
  refreshTokens = refreshTokens.filter((t) => t !== token);
  res.status(200).json({ message: "Logged out successfully" });
});

// Protected route
app.get("/protected", (req, res) => {
  const authHeader = req.headers.authorization;
  const token = authHeader && authHeader.split(" ")[1];

  if (!token) return res.status(401).json({ error: "Unauthorized" });

  try {
    const decoded = jwt.verify(token, ACCESS_TOKEN_SECRET);
    res.json({ message: "Welcome to the protected route!", user: decoded });
  } catch {
    res.status(403).json({ error: "Invalid or expired token" });
  }
});

// Start the server
app.listen(3001, () => {
  console.log("Server running on http://localhost:3001");
});

Step 3: Set Up the Frontend

3.1 Initialize the React App

npx create-react-app client
cd client
npm install axios

Step 4: Create React Components

4.1 Create an AuthContext

Inside the src folder, create a new file AuthContext.js:

import React, { createContext, useState, useContext } from "react";
import axios from "axios";

const AuthContext = createContext();

export const AuthProvider = ({ children }) => {
  const [user, setUser] = useState(null);

  const login = async (username, password) => {
    try {
      const { data } = await axios.post("http://localhost:3001/login", {
        username,
        password,
      });
      localStorage.setItem("accessToken", data.accessToken);
      localStorage.setItem("refreshToken", data.refreshToken);
      setUser({ username });
    } catch (err) {
      console.error(err);
      alert("Invalid credentials");
    }
  };

  const logout = async () => {
    const refreshToken = localStorage.getItem("refreshToken");
    await axios.post("http://localhost:3001/logout", { token: refreshToken });
    localStorage.removeItem("accessToken");
    localStorage.removeItem("refreshToken");
    setUser(null);
  };

  return (
    <AuthContext.Provider value={{ user, login, logout }}>
      {children}
    </AuthContext.Provider>
  );
};

export const useAuth = () => useContext(AuthContext);

4.2 Create Login and Protected Components

Login Component
import React, { useState } from "react";
import { useAuth } from "./AuthContext";

const Login = () => {
  const { login } = useAuth();
  const [username, setUsername] = useState("");
  const [password, setPassword] = useState("");

  return (
    <div>
      <h1>Login</h1>
      <input
        type="text"
        placeholder="Username"
        value={username}
        onChange={(e) => setUsername(e.target.value)}
      />
      <input
        type="password"
        placeholder="Password"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
      />
      <button onClick={() => login(username, password)}>Login</button>
    </div>
  );
};

export default Login;
Protected Component
import React, { useEffect, useState } from "react";
import axios from "axios";

const Protected = () => {
  const [message, setMessage] = useState("");

  useEffect(() => {
    const fetchData = async () => {
      try {
        const token = localStorage.getItem("accessToken");
        const { data } = await axios.get("http://localhost:3001/protected", {
          headers: { Authorization: `Bearer ${token}` },
        });
        setMessage(data.message);
      } catch {
        setMessage("Unauthorized");
      }
    };
    fetchData();
  }, []);

  return <div>{message}</div>;
};

export default Protected;

Step 5: Run the Application

  1. Start the backend server:
   node server.js
  1. Start the React frontend:
   npm start

Final Thoughts

Congratulations! You've built a secure authentication system with Node.js, JWT, and React. For more tutorials, visit my YouTube Channel.


This content originally appeared on DEV Community and was authored by Pedro Henrique Machado


Print Share Comment Cite Upload Translate Updates
APA

Pedro Henrique Machado | Sciencx (2025-01-10T17:16:11+00:00) JWT Authentication With NodeJS. Retrieved from https://www.scien.cx/2025/01/10/jwt-authentication-with-nodejs/

MLA
" » JWT Authentication With NodeJS." Pedro Henrique Machado | Sciencx - Friday January 10, 2025, https://www.scien.cx/2025/01/10/jwt-authentication-with-nodejs/
HARVARD
Pedro Henrique Machado | Sciencx Friday January 10, 2025 » JWT Authentication With NodeJS., viewed ,<https://www.scien.cx/2025/01/10/jwt-authentication-with-nodejs/>
VANCOUVER
Pedro Henrique Machado | Sciencx - » JWT Authentication With NodeJS. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2025/01/10/jwt-authentication-with-nodejs/
CHICAGO
" » JWT Authentication With NodeJS." Pedro Henrique Machado | Sciencx - Accessed . https://www.scien.cx/2025/01/10/jwt-authentication-with-nodejs/
IEEE
" » JWT Authentication With NodeJS." Pedro Henrique Machado | Sciencx [Online]. Available: https://www.scien.cx/2025/01/10/jwt-authentication-with-nodejs/. [Accessed: ]
rf:citation
» JWT Authentication With NodeJS | Pedro Henrique Machado | Sciencx | https://www.scien.cx/2025/01/10/jwt-authentication-with-nodejs/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.