التفويض والمصادقة في TypeScript: من النظرية إلى التطبيق
في تطوير الويب الحديث، أمان التطبيقات هو حجر الزاوية. TypeScript، كإضافة صارمة في كتابة الأنواع فوق JavaScript، يوفر أدوات قوية لبناء أنظمة موثوقة لـ المصادقة (التحقق من هوية المستخدم) والتفويض (التحقق من صلاحيات الوصول). في هذه المقالة، سنستعرض المفاهيم الأساسية، المكتبات الشائعة، ونكتب مثالاً عملياً باستخدام TypeScript.
المفاهيم الأساسية: المصادقة مقابل التفويض
غالباً ما يتم الخلط بين هذين المصطلحين. دعنا نوضح الفرق بوضوح:
- المصادقة (Authentication) — عملية التحقق من هويتك. على سبيل المثال، تسجيل الدخول باستخدام اسم المستخدم وكلمة المرور أو عبر خدمة طرف ثالث (Google، GitHub).
- التفويض (Authorization) — عملية التحقق من الإجراءات المسموح لك القيام بها. على سبيل المثال، الوصول إلى لوحة التحكم أو القدرة على حذف المنشورات.
في TypeScript، يتم تنفيذ هذه العمليات من خلال middleware (معالجات وسيطة) تتحقق من الرموز المميزة (tokens) أو الجلسات قبل معالجة الطلب.
المكتبات الشائعة لـ TypeScript
لتنفيذ التفويض والمصادقة في مشاريع TypeScript، يتم استخدام ما يلي غالباً:
jsonwebtoken— للعمل مع JWT (JSON Web Tokens).bcrypt— لتجزئة كلمات المرور.passport(مع الأنواع@types/passport) — middleware مرن لـ Express.express-session— لإدارة الجلسات على الخادم.crypto— وحدة Node.js المدمجة للعمل مع التجزئة.
مثال عملي: مصادقة JWT باستخدام TypeScript
لننظر في إنشاء REST API بسيط مع مصادقة عبر JWT. سيكون المثال باستخدام Express + TypeScript.
الخطوة 1. تثبيت التبعيات
npm install express jsonwebtoken bcrypt dotenvnpm install -D typescript @types/express @types/jsonwebtoken @types/bcrypt ts-node nodemonالخطوة 2. إعداد TypeScript (tsconfig.json)
{ "compilerOptions": { "target": "ES2020", "module": "commonjs", "outDir": "./dist", "rootDir": "./src", "strict": true, "esModuleInterop": true }}الخطوة 3. إنشاء middleware للمصادقة
// src/middleware/auth.tsimport { Request, Response, NextFunction } from 'express';import jwt from 'jsonwebtoken';
interface UserPayload { id: string; email: string;}
// توسيع واجهة Request لتخزين بيانات المستخدمdeclare global { namespace Express { interface Request { user?: UserPayload; } }}
export const authenticate = ( req: Request, res: Response, next: NextFunction): void => { const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith('Bearer ')) { res.status(401).json({ message: 'الرمز المميز غير مقدم' }); return; }
const token = authHeader.split(' ')[1];
try { const decoded = jwt.verify( token, process.env.JWT_SECRET || 'default_secret' ) as UserPayload; req.user = decoded; next(); } catch (error) { res.status(401).json({ message: 'الرمز المميز غير صالح' }); }};الخطوة 4. Middleware للتفويض حسب الأدوار
// src/middleware/authorize.tsimport { Request, Response, NextFunction } from 'express';
export const authorize = (...allowedRoles: string[]) => { return (req: Request, res: Response, next: NextFunction): void => { // نفترض أن الدور مخزن في req.user بعد المصادقة const userRole = (req as any).user?.role || 'user';
if (!allowedRoles.includes(userRole)) { res.status(403).json({ message: 'الوصول ممنوع' });