JSON Web Token (JWT) Security: Best Practices for Token Architecture
ব্যাকএন্ডে ইউজার সেশন ট্র্যাকিং বা অথেনটিকেশনের জন্য **JSON Web Token (JWT)** একটি স্ট্যান্ডার্ড সলিউশন। তবে অনেক ডেভলপার টোকেন জেনারেট করার পর তা ফ্রন্টএন্ডের `localStorage` এ স্টোর করে রাখেন, যা মারাত্মক সিকিউরিটি থ্রেট। এর ফলে সাইটে কোনো কাস্টম স্ক্রিপ্ট বা XSS (Cross-Site Scripting) অ্যাটাক হলে হ্যাকার সহজেই টোকেন চুরি করে ইউজারের অ্যাকাউন্ট হাইজ্যাক করতে পারে।
সিকিউরড আর্কিটেকচারের জন্য অবশ্যই টোকেনকে **HttpOnly Cookie** এর ভেতর সেট করতে হবে, যা জাভাস্ক্রিপ্ট দিয়ে রিড করা অসম্ভব।
১. টোকেন সাইনিং এবং সিকিউর কুকি ইনজেকশন
লগইন ভেরিফিকেশনের পর কীভাবে এক্সপ্রেস অ্যাপ থেকে কাস্টম রিফ্রেশ ও অ্যাক্সেস টোকেন জেনারেট করে কুকিতে পুশ করবেন, তা নিচে দেখানো হলো:
const jwt = require('jsonwebtoken');
app.post('/api/auth/login', (req, res) => {
// ইউজার ভেরিফিকেশন লজিক শেষ হওয়ার পর...
const userPayload = { userId: "ahyan_dev_007", role: "admin" };
// ১. স্বল্পমেয়াদী অ্যাক্সেস টোকেন জেনারেট (১৫ মিনিট মেয়াদ)
const accessToken = jwt.sign(userPayload, 'ACCESS_SECRET_KEY', { expiresIn: '15m' });
// ২. দীর্ঘমেয়াদী রিফ্রেশ টোকেন জেনারেট (৭ দিন মেয়াদ)
const refreshToken = jwt.sign(userPayload, 'REFRESH_SECRET_KEY', { expiresIn: '7d' });
// ৩. টোকেন দুটি অত্যন্ত সুরক্ষিত HttpOnly কুকিতে সেট করা
res.cookie('accessToken', accessToken, {
httpOnly: true, // জাভাস্ক্রিপ্ট চুরি প্রতিরোধ করবে
secure: true, // শুধুমাত্র HTTPS প্রোটোকলে কাজ করবে
sameSite: 'strict', // CSRF অ্যাটাক প্রোটেকশন
maxAge: 15 * 60 * 1000 // ১৫ মিনিট
});
res.json({ success: true, status: "Pipeline secure. Authenticated!" });
});
ধাপ ২: মিডলওয়্যার ভেরিফিকেশন গেটওয়ে
যেকোনো প্রোটেক্টেড এপিআই রাউটে রিকোয়েস্ট আসার পর ইনকামিং কুকি টোকেন ডিক্রিপ্ট এবং অথরাইজ করার সিকিউর লজিক:
const verifySecureToken = (req, res, next) => {
// কুকি হেডার থেকে টোকেন এক্সট্র্যাক্ট করা
const token = req.cookies.accessToken;
if (!token) return res.status(401).json({ error: "Access denied. Token missing." });
try {
const verified = jwt.verify(token, 'ACCESS_SECRET_KEY');
req.user = verified;
next(); // পরবর্তী এক্সিকিউশনে পাস করা
} catch (err) {
res.status(403).json({ error: "Invalid token or session expired." });
}
};
প্রো-টিপ: প্রোডাকশনে কখনো jwt.decode() ব্যবহার করবেন না। ডিকোড শুধুমাত্র টোকেনের ভেতরের ডেটা রিড করে কিন্তু ক্রিপ্টোগ্রাফিক সিগনেচার ভেরিফাই করে না। সবসময় jwt.verify() ব্যবহার নিশ্চিত করুন।