এখন পর্যন্ত আমাদের দোকানের সব 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.
| Step | What Happens |
|---|---|
| 1 | User logs in with username & password |
| 2 | Server returns a JWT token |
| 3 | Browser stores token in localStorage |
| 4 | Every API call sends token in header |
| 5 | Server 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!
💬 মন্তব্য / Comments