OAuth 2.0 وتفويض JWT في TypeScript: دليل كامل
تتطلب تطبيقات الويب الحديثة وواجهات برمجة التطبيقات (API) آليات موثوقة للمصادقة والتفويض. المعياران الأكثر شيوعًا — OAuth 2.0 و JWT (JSON Web Tokens) — غالبًا ما يُستخدمان معًا لإنشاء أنظمة آمنة وقابلة للتوسع. في هذه المقالة، سنشرح كيفية تنفيذ تفويض OAuth 2.0 و JWT في TypeScript باستخدام Express.js والمكتبات الشائعة.
ما هو OAuth 2.0 و JWT؟
OAuth 2.0 هو بروتوكول تفويض يسمح للتطبيقات بالحصول على وصول محدود إلى موارد المستخدم دون نقل بيانات اعتماده. يُستخدم على نطاق واسع لتسجيل الدخول عبر الشبكات الاجتماعية (Google, GitHub, Facebook).
JWT (JSON Web Token) هو رمز مضغوط ومكتفي ذاتيًا يحتوي على معلومات حول المستخدم ويمكن التحقق منه دون الرجوع إلى قاعدة البيانات. غالبًا ما يُستخدم JWT كتنسيق لرموز الوصول (access-tokens) في OAuth 2.0.
معًا، يشكلان آلية قوية: يدير OAuth 2.0 عملية إصدار الرموز، بينما يضمن JWT نقلها الآمن والتحقق منها.
إعداد المشروع وتثبيت التبعيات
لننشئ مشروعًا جديدًا في TypeScript. تأكد من تثبيت Node.js (الإصدار 18+).
mkdir oauth-jwt-typescriptcd oauth-jwt-typescriptnpm init -yقم بتثبيت التبعيات الضرورية:
npm install express jsonwebtoken passport passport-google-oauth20 dotenv bcryptjsnpm install -D typescript @types/express @types/jsonwebtoken @types/passport @types/passport-google-oauth20 @types/bcryptjs ts-node nodemonأنشئ ملف tsconfig.json:
{ "compilerOptions": { "target": "ES2020", "module": "commonjs", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "outDir": "./dist" }, "include": ["src/**/*"]}هيكل المشروع:
src/ ├── config/ │ └── passport.ts ├── controllers/ │ └── authController.ts ├── middleware/ │ └── authMiddleware.ts ├── models/ │ └── user.ts ├── routes/ │ └── authRoutes.ts ├── services/ │ └── jwtService.ts └── app.tsتنفيذ تفويض JWT
تتكون رموز JWT من ثلاثة أجزاء: الرأس (header) والحمولة (payload) والتوقيع (signature). سننظر في التنفيذ الأساسي في TypeScript.
لننشئ خدمة للعمل مع JWT (src/services/jwtService.ts):
import jwt from 'jsonwebtoken';import dotenv from 'dotenv';
dotenv.config();
const ACCESS_SECRET = process.env.JWT_ACCESS_SECRET || 'access-secret-key';const REFRESH_SECRET = process.env.JWT_REFRESH_SECRET || 'refresh-secret-key';
export interface TokenPayload { userId: string; email: string; role: string;}
export const generateAccessToken = (payload: TokenPayload): string => { return jwt.sign(payload, ACCESS_SECRET, { expiresIn: '15m' });};
export const generateRefreshToken = (payload: TokenPayload): string => { return jwt.sign(payload, REFRESH_SECRET, { expiresIn: '7d' });};
export const verifyAccessToken = (token: string): TokenPayload => { return jwt.verify(token, ACCESS_SECRET) as TokenPayload;};
export const verifyRefreshToken = (token: string): TokenPayload => { return jwt.verify(token, REFRESH_SECRET) as TokenPayload;};لننشئ middleware للتحقق من JWT (src/middleware/authMiddleware.ts):
import { Request, Response, NextFunction } from 'express';import { verifyAccessToken } from '../services/jwtService';
export interface AuthRequest extends Request { user?: { userId: string; email: string; role: string; };}
export const authenticateJWT = (req: AuthRequest, res: Response, next: NextFunction): void => { const authHea
```