আপনার login endpoint সবার জন্য খোলা। একজন attacker script লিখে প্রতি সেকেন্ডে ১০০টা করে password চেষ্টা করতে পারে - কোনো বাধা নেই। কিংবা ধরুন অন্য একটা website থেকে আপনার API-তে অনাকাঙ্ক্ষিত request আসছে। এই পর্বটা সেই দরজাগুলো বন্ধ করার - যেগুলো না থাকলে বাকি সব ভালো কোড অর্থহীন।
Rate limiting - গতি বেঁধে দেওয়া
Rate limiting মানে নির্দিষ্ট সময়ে নির্দিষ্ট সংখ্যার বেশি request নেওয়া হবে না। যেমন একই IP থেকে ১৫ মিনিটে ১০০টা request, login-এর ক্ষেত্রে আরও কড়া - ৫ বার ব্যর্থ হলেই কিছুক্ষণ অপেক্ষা। এতে brute force আক্রমণ প্রায় অসম্ভব হয়ে যায়, আর অস্বাভাবিক চাপে server-ও বাঁচে।
import rateLimit from "express-rate-limit";
const loginLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // ১৫ মিনিট
max: 20, // এই সময়ে সর্বোচ্চ ২০ বার
message: { success: false, message: "অনেকবার চেষ্টা হয়েছে, কিছুক্ষণ পরে আবার চেষ্টা করুন" },
});
app.post("/auth/login", loginLimiter, loginController);CORS - browser-এর দারোয়ান, server-এর না
CORS নিয়ে সবচেয়ে বড় ভুল ধারণা: এটা server-এর নিরাপত্তা ব্যবস্থা। আসলে CORS হলো browser-এর নিয়ম - এক origin-এর (domain-এর) website অন্য origin-এর API থেকে data পড়তে পারবে কিনা, সেটা browser ঠেকায়। Server বলে দেয় কোন কোন origin-কে অনুমতি আছে। অচেনা origin থেকে browser-এ চলা কোড data পড়তে পারবে না - কিন্তু Postman বা script দিয়ে request আটকাবে না CORS, সেটার জন্য auth আর rate limit-ই ভরসা।
Preflight হলো এর আগাম যাচাই: আসল request-এর আগে browser একটা ছোট OPTIONS request পাঠিয়ে জিজ্ঞেস করে 'এই origin থেকে এই ধরনের request পাঠাতে পারি?' Server হ্যাঁ বললেই আসল request যায়। Frontend থেকে 'CORS error' দেখলে এর মানে প্রায় সবসময়ই এই - server-এর allowed origin তালিকায় আপনার frontend-এর domain-টা নেই।
import cors from "cors";
import helmet from "helmet";
app.use(helmet()); // নিরাপত্তা header নিজে থেকে বসিয়ে দেয়
app.use(cors({ origin: ["https://your-frontend.com"], credentials: true }));Helmet এক লাইনে অনেকগুলো নিরাপত্তা header বসিয়ে দেয় - যেমন site-কে অন্য site-এর frame-এ ঢোকানো ঠেকানো। আর input sanitization মানে user-এর দেওয়া data বিশ্বাস না করা - validation (পর্ব ৪) তার প্রথম ধাপ, তার উপর database query-তে সবসময় parameterized উপায় ব্যবহার করা, যাতে SQL injection-এর সুযোগই না থাকে। Prisma আর prepared statement এটা নিজে থেকেই করে - raw string জোড়া দিয়ে query বানালেই বিপদ।
সবাই যে ভুলটা করে
CORS-এ origin: "*" দিয়ে সবাইকে অনুমতি দিয়ে দেওয়া, বিশেষ করে credentials চালু থাকা অবস্থায় - এটা দরজা খুলে দেওয়ার সমান। অনুমতি শুধু নিজের frontend domain-কেই দিন। আরেকটা ভুল: CORS-কে নিরাপত্তা ভেবে auth দুর্বল রাখা।
আজকের Practice
আপনার API-তে helmet বসান, CORS শুধু নিজের frontend origin-এর জন্য খুলুন, আর login endpoint-এ কড়া rate limit দিন। তারপর script দিয়ে পরপর ২৫ বার login চেষ্টা করে দেখুন limiter ঠিকমতো থামাচ্ছে কিনা।
Interview-এ কীভাবে বলবেন
Rate limiting দিয়ে আমি brute force আর অস্বাভাবিক চাপ ঠেকাই, বিশেষ করে login-এর মতো সংবেদনশীল endpoint-এ। CORS হলো browser-এর origin যাচাই - আমি শুধু নিজের frontend domain-কেই অনুমতি দিই, কখনো সবার জন্য খুলে দিই না। সাথে helmet দিয়ে নিরাপত্তা header, আর সব query parameterized রেখে injection ঠেকাই।