احراز هویت کاربران در Node.js
احراز هویت کاربران (Authentication) یکی از ارکان اصلی در ساخت اپلیکیشنهای وب است. در محیط Node.js با توجه به اکوسیستم غنی از ماژولها و فریمورکها، پیادهسازی احراز هویت میتواند از ساده تا پیچیده متغیر باشد. هدف این مقاله توضیح مفاهیم پایه، نمونههای عملی و بهترین شیوههای امنیتی است تا بتوانید یک سیستم احراز هویت امن و مقیاسپذیر بسازید.
مفاهیم کلیدی
- تأیید هویت (Authentication): اثبات اینکه کاربر چه کسی است.
- مجوز (Authorization): اعطای دسترسی به منابع بر اساس نقشها یا مجوزها.
- Session: ذخیرهٔ وضعیت ورود کاربر در سرور یا دیتابیس.
- JWT: توکنهای JSON Web Token برای احراز هویت بدون وضعیت (stateless).
- OAuth / OpenID Connect: پروتکلهای استاندارد برای ورود با سرویسهای ثالث.
الگوهای متداول در Node.js
- Sessions با express-session و ذخیرهسازی در Redis یا دیتابیس
- Token-based با JWT
- استفاده از Passport.js برای یکپارچهسازی استراتژیهای مختلف (local, oauth)
نمونه عملی: ثبتنام و ورود ساده با bcrypt و JWT
const express = require('express');
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());
const users = []; // برای نمونه - در عمل از دیتابیس استفاده کنید
const JWT_SECRET = 'your-secret-key';
const SALT_ROUNDS = 10;
app.post('/register', async (req, res) => {
const { username, password } = req.body;
const hashed = await bcrypt.hash(password, SALT_ROUNDS);
users.push({ id: users.length + 1, username, password: hashed });
res.status(201).json({ message: 'user registered' });
});
app.post('/login', async (req, res) => {
const { username, password } = req.body;
const user = users.find(u => u.username === username);
if (!user) return res.status(401).json({ error: 'invalid credentials' });
const ok = await bcrypt.compare(password, user.password);
if (!ok) return res.status(401).json({ error: 'invalid credentials' });
const token = jwt.sign({ sub: user.id, username: user.username }, JWT_SECRET, { expiresIn: '15m' });
res.json({ token });
});
app.listen(3000);توضیح: این کد یک API ساده ثبتنام و ورود نمایش میدهد. رمز عبور با bcrypt هش میشود و پس از ورود موفق، یک JWT تولید میگردد. در عمل نباید از آرایهٔ حافظه برای ذخیرهٔ کاربر استفاده کنید و کلید مخفی باید از متغیرهای محیطی خوانده شود.
نکات امنیتی برای کد بالا
- رمز عبور را با bcrypt یا Argon2 هش کنید.
- کلیدهای مخفی نباید در سورس قرار گیرند؛ از env vars یا secret manager استفاده کنید.
- برای تولید توکنهای طولانیمدت از refresh token استفاده کنید و آنها را در دیتابیس یا حافظه امن ذخیره کنید.
- از HTTPS برای تمام ارتباطات استفاده کنید و کوکیها را با HttpOnly و Secure ست کنید.
نمونه: پیادهسازی ساده Refresh Token
// assume existing login that issues accessToken and refreshToken
app.post('/token', (req, res) => {
const { refreshToken } = req.body;
// validate refreshToken exists in DB and not revoked
try {
const payload = jwt.verify(refreshToken, REFRESH_SECRET);
const accessToken = jwt.sign({ sub: payload.sub }, JWT_SECRET, { expiresIn: '15m' });
res.json({ accessToken });
} catch (err) {
res.status(401).json({ error: 'invalid refresh token' });
}
});توضیح: این مسیر یک refresh token را اعتبارسنجی میکند و یک access token جدید صادر مینماید. توجه کنید که refresh tokenها معمولاً طولانیتر و با طول عمر بیشتر هستند و باید در دیتابیس همراه با وضعیت (مثلاً revoked) نگهداری شوند.
مقایسه سریع: JWT در مقابل Session
| ویژگی | JWT | Session |
|---|---|---|
| حالت (Statefulness) | Stateless | Stateful |
| مقیاسپذیری | خوب برای سرویسهای توزیعشده | نیاز به سینک/ذخیرهسازی (Redis) |
| باطلسازی سریع توکن | پیچیدهتر (لیست سیاه یا کوتاهمدت) | سادهتر (حذف session از سرور) |
بهترین شیوهها و حملات معمول
- استفاده از HttpOnly و Secure برای کوکیها تا از سرقت از طریق XSS جلوگیری شود.
- اجرای rate limiting برای endpointهای ورود با ابزارهایی مثل express-rate-limit.
- محافظت در برابر CSRF (هنگام استفاده از کوکی) با توکن CSRF یا SameSite=strict.
- لاگبرداری و مانیتورینگ ورودهای ناموفق و تلاشهای مشکوک.
استفاده از Passport.js و OAuth
اگر میخواهید ورود با گوگل، فیسبوک یا سایر ارائهدهندگان را اضافه کنید، Passport.js یک راه ساده و استاندارد فراهم میکند. Passport دارای استراتژیهای oauth2 و openidconnect است که پیادهسازی ورود ثالث را تسریع میکند.
نتیجهگیری و توصیههای عملی
در اغلب پروژهها توصیه میشود:
- برای اپهای کوچک و اپی آیهای توزیعشده از JWT به همراه refresh token استفاده کنید.
- برای برنامههای سنتی web app از session با ذخیرهسازی امن (مثلاً Redis) بهره ببرید.
- همیشه رمزها را هش کنید، از HTTPS استفاده کنید و کلیدهای مخفی را ایمن نگه دارید.
- برای ورود با سرویسهای خارجی از Passport یا کتابخانههای رسمی استفاده کنید تا از پیچیدگیهای OAuth خلاص شوید.
در صورت نیاز میتوانم کد کامل یک نمونهٔ production-ready با Redis، refresh-token و Passport را آماده کرده و توضیحات پیادهسازی آن را ارائه دهم.
آیا این مطلب برای شما مفید بود ؟




