এখন পর্যন্ত আমাদের দোকানের সব API খোলা ছিল—যে কেউ চাইলেই প্রোডাক্ট যোগ, এডিট, ডিলিট করতে পারত। বাস্তব দুনিয়ায় এটা চলতে পারে না। আজ আমরা JWT (JSON Web Token) লগইন সিস্টেম তৈরি করবো, যাতে শুধুমাত্র লগইন করা অনুমোদিত ইউজারই API ব্যবহার করতে পারে।

JWT কী এবং কেন দরকার?

JWT হলো একটি ডিজিটাল "পরিচয়পত্র"। ইউজার লগইন করলে সার্ভার তাকে একটি সই-করা টোকেন দেয়। এরপর প্রতিটি API কলে সেই টোকেন পাঠাতে হয়—ঠিক যেন প্রতিবার গেটে পরিচয়পত্র দেখানো। সার্ভার টোকেন যাচাই করে, আসল কি না দেখে, তারপরই কাজ করে।

ধাপকী হয়?উদাহরণ
ইউজার লগইন করেইউজারনেম + পাসওয়ার্ড দিয়ে লগইন
সার্ভার JWT টোকেন দেয়একটা লম্বা স্ট্রিং—এটাই টোকেন
ব্রাউজার টোকেন localStorage-এ জমা রাখেপরের API কলের জন্য প্রস্তুত
প্রতিটি API কলে টোকেন পাঠানো হয়হেডারে Authorization: Bearer টোকেন
সার্ভার টোকেন চেক করেঠিক থাকলে API কাজ করে, না হলে 401

ধাপ ১: jsonwebtoken ইন্সটল করো

cd ~/shop-api
npm install jsonwebtoken

এই প্যাকেজটিই টোকেন তৈরি ও যাচাই করার সব কাজ করবে।

ধাপ ২: users.json তৈরি করো

আমরা প্রথমে একটি সাধারণ ইউজার লিস্ট বানাবো—পরবর্তীতে চাইলে আরও ইউজার যোগ করতে পারবে:

micro users.json

নিচের কোড পেস্ট করো:

[
  {
    "id": 1,
    "username": "admin",
    "password": "admin123",
    "role": "admin"
  }
]

ধাপ ৩: server.js-এ লগইন API ও middleware যোগ করো

cd ~/shop-api
micro server.js

সবার উপরে jsonwebtoken ইম্পোর্ট করো এবং সিক্রেট কী সেট করো:

const jwt = require('jsonwebtoken');
const SECRET_KEY = 'my_shop_secret_2026';

তারপর app.delete(...)-এর নিচে লগইন API যোগ করো:

// POST /login — লগইন করে JWT টোকেন পাওয়া
app.post('/login', (req, res) => {
  const { username, password } = req.body;
  const usersFile = path.join(__dirname, 'users.json');
  const users = JSON.parse(fs.readFileSync(usersFile, 'utf8'));
  const user = users.find(u => u.username === username && u.password === password);

  if (!user) {
    return res.status(401).json({ message: 'ভুল ইউজারনেম বা পাসওয়ার্ড' });
  }

  // টোকেন তৈরি (id, username, role সহ)
  const token = jwt.sign(
    { id: user.id, username: user.username, role: user.role },
    SECRET_KEY,
    { expiresIn: '24h' }  // ২৪ ঘণ্টা পর টোকেন expire হবে
  );

  res.json({ message: 'লগইন সফল', token, username: user.username });
});

এবার নিচের দিকে authMiddleware ফাংশন যোগ করো:

// AUTH MIDDLEWARE — যেসব রাউট প্রটেক্টেড, সেগুলোতে এটি ব্যবহার করবো
function authMiddleware(req, res, next) {
  const header = req.headers.authorization;
  if (!header) {
    return res.status(401).json({ message: 'টোকেন নেই। আগে লগইন করো।' });
  }
  const token = header.split(' ')[1];  // "Bearer টোকেন" থেকে শুধু টোকেন নিচ্ছি
  try {
    req.user = jwt.verify(token, SECRET_KEY);  // টোকেন যাচাই
    next();  // সব ঠিক — পরবর্তী কাজে যাও
  } catch (err) {
    res.status(401).json({ message: 'টোকেন অবৈধ অথবা expire হয়েছে' });
  }
}

লাইন-বাই-লাইন ব্যাখ্যা

লাইন/ব্লককী করছে?সহজ ভাষায়
jwt.sign(...)ইউজারের তথ্য নিয়ে টোকেন তৈরি"এই লোকটা কে, তা লিখে সিল-মারা চিঠি দাও"
jwt.verify(...)টোকেন যাচাই করে আসল কিনা"সিল আসল না নকল, দেখো"
expiresIn: '24h'টোকেনের মেয়াদ ২৪ ঘণ্টা"এই পাস ২৪ ঘণ্টা পর বাতিল"
authMiddlewareপ্রটেক্টেড রাউটের গার্ড"টোকেন ছাড়া ঢুকতে দেবে না"
req.headers.authorizationক্লায়েন্টের পাঠানো টোকেন পড়া"তোমার পরিচয়পত্র দেখাও"

ধাপ ৪: login.html তৈরি করো

cd ~/shop-api/public
micro login.html

নিচের কোড পেস্ট করো—একটি সুন্দর লগইন ফর্ম, যা টোকেন localStorage-এ জমা রাখে:

<!DOCTYPE html>
<html lang="bn">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>🔐 লগইন - মুদি দোকান</title>
  <style>
    * { margin:0; padding:0; box-sizing:border-box; }
    body { font-family:'Segoe UI', sans-serif; background:#f1f5f9; display:flex; align-items:center; justify-content:center; min-height:100vh; }
    .login-box { background:#fff; border-radius:16px; padding:2rem; max-width:400px; width:90%; box-shadow:0 4px 20px rgba(0,0,0,0.1); }
    h2 { text-align:center; margin-bottom:1.5rem; color:#1e293b; }
    input { width:100%; padding:0.75rem; margin-bottom:1rem; border:1px solid #cbd5e1; border-radius:8px; font-size:1rem; }
    button { width:100%; padding:0.75rem; background:#2563eb; color:#fff; border:none; border-radius:8px; font-size:1rem; font-weight:bold; cursor:pointer; }
    button:hover { background:#1d4ed8; }
    .error { color:#dc2626; text-align:center; margin-top:0.5rem; }
  </style>
</head>
<body>
  <div class="login-box">
    <h2>🔐 দোকান লগইন</h2>
    <input type="text" id="username" placeholder="ইউজারনেম" value="admin">
    <input type="password" id="password" placeholder="পাসওয়ার্ড" value="admin123">
    <button onclick="login()">লগইন</button>
    <div class="error" id="error"></div>
  </div>
  <script>
    async function login() {
      const username = document.getElementById('username').value;
      const password = document.getElementById('password').value;
      try {
        const res = await fetch('/login', {
          method:'POST',
          headers:{'Content-Type':'application/json'},
          body: JSON.stringify({ username, password })
        });
        const data = await res.json();
        if (!res.ok) { document.getElementById('error').textContent = '❌ ' + data.message; return; }
        localStorage.setItem('token', data.token);
        localStorage.setItem('username', data.username);
        window.location.href = 'products.html';
      } catch(err) { document.getElementById('error').textContent = '❌ নেটওয়ার্ক সমস্যা'; }
    }
  </script>
</body>
</html>

ধাপ ৫: API প্রটেক্ট করো

এখন POST, PUT, DELETE, এবং /sales রাউটে authMiddleware যোগ করো। যেমন:

app.post('/products', authMiddleware, (req, res) => { ... });
app.put('/products/:id', authMiddleware, (req, res) => { ... });
app.delete('/products/:id', authMiddleware, (req, res) => { ... });

এখন authMiddleware ছাড়া এসব API কাজ করবে না!

ধাপ ৬: টেস্ট করো

node server.js
termux-open-url http://localhost:3000/login.html

লগইন করলে টোকেন জমা হবে, তারপর products.html বা bill.html ব্যবহার করতে পারবে। লগইন ছাড়া API কল করলে 401 এরর আসবে।

আজ তুমি কী শিখলে

  • JWT — JSON Web Token কী এবং কেন দরকার
  • jwt.sign() — ইউজারের তথ্য দিয়ে টোকেন তৈরি
  • jwt.verify() — টোকেন যাচাই করে সত্যতা নিশ্চিত করা
  • authMiddleware — এক্সপ্রেস middleware দিয়ে API প্রটেক্ট করা
  • localStorage — ব্রাউজারে টোকেন সংরক্ষণ
  • Authorization Header — API কলে টোকেন পাঠানোর পদ্ধতি

পরবর্তী ও শেষ পর্বে আমরা SQLite ডাটাবেস শিখবো — JSON ফাইল ছেড়ে বাস্তব ডাটাবেস ব্যবস্থাপনা!

Until now, all our shop APIs were open—anyone could add, edit, or delete products. In the real world, that's not acceptable. Today we'll create a JWT (JSON Web Token) Login System so only authenticated users can use the API.

What is JWT and Why?

JWT is a digital "ID card". When a user logs in, the server gives them a signed token. Every subsequent API call must include this token—just like showing your ID at every checkpoint. The server verifies the token and only then processes the request.

StepWhat Happens
1User logs in with username & password
2Server returns a JWT token
3Browser stores token in localStorage
4Every API call sends token in header
5Server verifies token—allows or denies

Step 1: Install jsonwebtoken

npm install jsonwebtoken

Step 2: Create users.json

[{"id":1,"username":"admin","password":"admin123","role":"admin"}]

Step 3: Add login API & authMiddleware

const jwt = require('jsonwebtoken');
const SECRET_KEY = 'my_shop_secret_2026';

app.post('/login', (req, res) => { ... });
function authMiddleware(req, res, next) { ... }

Step 4: Create login.html

Build a login form that stores the token in localStorage.

Step 5: Protect API routes

Add authMiddleware to POST, PUT, DELETE, and /sales routes.

Next & final episode: SQLite Database — from JSON files to a real database!