التفويض والمصادقة في JavaScript (Node.js)
في تطوير الويب الحديث باستخدام Node.js، تعتبر أمان بيانات المستخدم والتحكم في الوصول من المهام الحيوية. المصادقة (التحقق من الهوية) والتفويض (التحقق من الصلاحيات) هما ركيزتا أي نظام آمن. في هذه المقالة، سنستعرض الأدوات والمكتبات الرئيسية لتنفيذ هذه الآليات على منصة Node.js.
المفاهيم الأساسية
المصادقة — هي عملية التحقق من أن المستخدم هو من يدّعي (عادةً عبر اسم المستخدم/كلمة المرور، الرموز المميزة، أو القياسات الحيوية). التفويض — هو تحديد الإجراءات والموارد المتاحة للمستخدم المُصادق عليه (الأدوار، صلاحيات الوصول).
المكتبات الشائعة لـ Node.js
1. Passport.js — استراتيجية مصادقة شاملة
Passport.js هي مكتبة الوسيط (middleware) الأكثر شيوعًا لـ Express. تدعم أكثر من 500 استراتيجية: محلية (اسم المستخدم/كلمة المرور)، OAuth2 (Google، Facebook، GitHub)، JWT، وغيرها الكثير.
const passport = require('passport');const LocalStrategy = require('passport-local').Strategy;
passport.use(new LocalStrategy( function(username, password, done) { User.findOne({ username: username }, function (err, user) { if (err) { return done(err); } if (!user) { return done(null, false, { message: 'اسم المستخدم غير صحيح' }); } if (!user.validPassword(password)) { return done(null, false, { message: 'كلمة المرور غير صحيحة' }); } return done(null, user); }); }));
// تسلسل وإلغاء تسلسل المستخدمpassport.serializeUser(function(user, done) { done(null, user.id);});
passport.deserializeUser(function(id, done) { User.findById(id, function(err, user) { done(err, user); });});2. JSON Web Tokens (JWT) — مصادقة بدون جلسات
مكتبة jsonwebtoken تسمح بإنشاء والتحقق من رموز JWT. هذا مثالي لواجهات برمجة التطبيقات REST وتطبيقات الصفحة الواحدة (SPA).
const jwt = require('jsonwebtoken');const secretKey = process.env.JWT_SECRET;
// إنشاء رمز مميز عند تسجيل الدخولconst token = jwt.sign( { userId: user.id, role: user.role }, secretKey, { expiresIn: '24h' });
// وسيط (Middleware) للتحقق من الرمز المميزfunction authMiddleware(req, res, next) { const authHeader = req.headers['authorization']; const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN
if (!token) return res.status(401).json({ error: 'الرمز المميز غير مقدم' });
jwt.verify(token, secretKey, (err, decoded) => { if (err) return res.status(403).json({ error: 'رمز مميز غير صالح' }); req.user = decoded; next(); });}3. bcrypt — تجزئة آمنة لكلمات المرور
لا تقم أبدًا بتخزين كلمات المرور كنص عادي! bcrypt هو المعيار الذهبي للتجزئة مع إضافة الملح (salting).
const bcrypt = require('bcrypt');const saltRounds = 10;
// تجزئة كلمة المرور عند التسجيلasync function hashPassword(plainPassword) { const salt = await bcrypt.genSalt(saltRounds); const hash = await bcrypt.hash(plainPassword, salt); return hash;}
// التحقق من كلمة المرور عند تسجيل الدخولasync function checkPassword(plainPassword, hash) { return await bcrypt.compare(plainPassword, hash);}4. express-session + connect-redis — إدارة الجلسات
لتطبيقات الويب التقليدية مع جلسات الخادم، استخدم express-session مع Redis للتوسع.
const session = require('express-session');const RedisStore = require('connect-redis')(session);
app.use(session({ store: new RedisStore({ client: redisClient }), secret: process.env.SESSION_SECRET, resave: false, saveUninitialized: false, cookie: { secure: process.env.NODE_ENV === 'production', // HTTPS httpOnly: true, maxAge: 24 * 60 * 60 * 1000 // يوم واحد }}))