একটা সত্যি কথা দিয়ে শুরু করি: কোনো একদিন আপনার database ফাঁস হতেই পারে - backup ভুল হাতে গেল, কিংবা কোনো bug দিয়ে কেউ dump করে নিল। সেদিন যদি password-গুলো plain text-এ থাকে, তাহলে user-দের সব account শেষ - কারণ বেশিরভাগ মানুষ একই password সব জায়গায় ব্যবহার করে। তাই password কখনোই plain text-এ রাখা যাবে না, কখনোই না।
Hashing মানে কী, encryption থেকে আলাদা কীভাবে
Hashing একমুখী - password থেকে hash বানানো যায়, কিন্তু hash থেকে password ফিরে পাওয়া যায় না। Login-এর সময় user যে password দেয়, সেটাকে আবার hash করে database-এর hash-এর সাথে মেলানো হয়। bcrypt ব্যবহার করার কারণ হলো এটা ইচ্ছা করে ধীর - attacker কোটি কোটি guess করতে গেলে তার খরচ আকাশছোঁয়া হয়ে যায়। সাথে salt নিজে থেকেই যোগ হয়।
import bcrypt from "bcrypt";
// signup-এর সময়
const hash = await bcrypt.hash(plainPassword, 10);
await db.user.create({ data: { email, password: hash } });
// login-এর সময়
const ok = await bcrypt.compare(plainPassword, user.password);
if (!ok) return res.status(401).json({ success: false, message: "Invalid credentials" });JWT - login-এর প্রমাণপত্র
Login সফল হলে server একটা JWT (JSON Web Token) দেয়। Token-টা তিন ভাগে ভাগ করা - header, payload, signature। Payload-এ থাকে user-এর id আর role-এর মতো ছোট তথ্য, আর signature নিশ্চিত করে মাঝখানে কেউ token বদলে দেয়নি - কারণ বদলাতে গেলে server-এর secret লাগবে, যেটা শুধু server-ই জানে।
import jwt from "jsonwebtoken";
const accessToken = jwt.sign(
{ userId: user.id, role: user.role },
process.env.JWT_SECRET,
{ expiresIn: "15m" }
);দুইটা নিয়ম মনে রাখুন। এক, payload-এ password বা ব্যক্তিগত তথ্য রাখবেন না - token যে কেউ decode করে পড়তে পারে, শুধু বদলাতে পারে না। দুই, access token-এর মেয়াদ ছোট রাখুন - ১৫ মিনিট থেকে ১ ঘণ্টা। কারণ একবার token চুরি হলে সেটা বাতিল করার সহজ উপায় নেই, মেয়াদ ছোট হলে ক্ষতিও ছোট হয়। এই ছোট মেয়াদের সমস্যাটাই পরের পর্বে refresh token দিয়ে সমাধান করব।
সবাই যে ভুলটা করে
সবচেয়ে বিপজ্জনক ভুল দুটো: password plain text বা শুধু MD5/SHA দিয়ে রাখা (এগুলো এত দ্রুত যে attacker সেকেন্ডে কোটি guess করতে পারে), আর JWT secret কোডে hardcode করে GitHub-এ তুলে দেওয়া। Secret সবসময় environment variable-এ থাকবে।
আজকের Practice
Signup আর login endpoint বানান। Signup-এ bcrypt দিয়ে password hash করে সেভ করুন, login-এ compare করে মিললে 15 মিনিট মেয়াদের access token ফেরত দিন। নিজে একবার ভুল password দিয়ে দেখুন সঠিক 401 আসে কিনা।
Interview-এ কীভাবে বলবেন
Password আমি bcrypt দিয়ে hash করে রাখি - এটা ধীর আর salted, তাই database ফাঁস হলেও password ফেরত পাওয়া প্রায় অসম্ভব। Login-এর পর ছোট মেয়াদের JWT access token দিই - payload-এ শুধু user id আর role, কোনো sensitive তথ্য নয়, আর secret থাকে environment variable-এ।