NestJS — Node.js للمؤسسات

المصادقة باستخدام Passport

17 دقيقة الدرس 26 من 48

المصادقة باستخدام Passport

تُجيب المصادقة (Authentication) عن "من أنت؟" — بالتحقّق من هوية المستخدم. يدمج NestJS مكتبة Passport، مكتبة المصادقة الفعلية لـ Node.js، عبر @nestjs/passport. تُنظّم Passport المصادقة في استراتيجيات، ونبدأ بأبسطها: التحقّق من بريد وكلمة مرور.

المصادقة مقابل التفويض

سؤالان مختلفان. تؤكّد المصادقة الهوية (من أنت — تسجيل الدخول). ويقرّر التفويض الصلاحيات (ما يُسمح لك به — الأدوار). تغطّي هذه المرحلة كليهما، بدءًا بالمصادقة. لا تخلط بينهما.

الأجزاء

  • استراتيجية Passport — قاعدة التحقّق من بيانات اعتماد (محلية، JWT، OAuth…).
  • AuthGuard — حارس يشغّل استراتيجية على مسار.
  • AuthService — كودك الذي يفحص المستخدم مقابل قاعدة البيانات.

الإعداد

npm install @nestjs/passport passport passport-local npm install -D @types/passport-local

منطق التحقّق

تحتوي AuthService الفحص الفعلي: أوجِد المستخدم وقارن كلمة المرور (مُجزّأة، لا نصًّا صريحًا — باستخدام bcrypt أو argon2):

import { Injectable, UnauthorizedException } from '@nestjs/common'; import * as bcrypt from 'bcrypt'; @Injectable() export class AuthService { constructor(private users: UsersService) {} async validateUser(email: string, password: string) { const user = await this.users.findByEmail(email); if (user && (await bcrypt.compare(password, user.passwordHash))) { const { passwordHash, ...safe } = user; return safe; // لا تُعِد التجزئة أبدًا } return null; // بيانات اعتماد غير صالحة } }

الاستراتيجية المحلية

تربط الاستراتيجية Passport بتحقّقك. تُستدعى validate() ببيانات الاعتماد؛ وإعادة مستخدم تُرفِقه بالطلب، بينما الرمي يرفض الدخول:

import { Strategy } from 'passport-local'; import { PassportStrategy } from '@nestjs/passport'; import { Injectable, UnauthorizedException } from '@nestjs/common'; @Injectable() export class LocalStrategy extends PassportStrategy(Strategy) { constructor(private authService: AuthService) { super({ usernameField: 'email' }); // الحقل الافتراضي 'username' } async validate(email: string, password: string) { const user = await this.authService.validateUser(email, password); if (!user) throw new UnauthorizedException(); return user; // يصبح request.user } }

حماية مسار الدخول

طبّق AuthGuard('local') على معالج الدخول. تشغّل Passport الاستراتيجية أولًا؛ وإن نجحت، تُعبَّأ request.user:

import { Controller, Post, UseGuards, Request } from '@nestjs/common'; import { AuthGuard } from '@nestjs/passport'; @Controller('auth') export class AuthController { @UseGuards(AuthGuard('local')) @Post('login') login(@Request() req) { return req.user; // الاستراتيجية تحقّقت وأرفقت المستخدم } }
جزّئ كلمات المرور دائمًا؛ لا تُخزّنها أو تقارنها نصًّا صريحًا أبدًا. استخدم bcrypt أو argon2، وقارن بدالّة المكتبة ثابتة الزمن، ولا تُعِد التجزئة في استجابة API أبدًا. كلمات المرور النصّية الصريحة فشل أمني لا يُغتفَر.
أعِد استخدام الحُرّاس من قبل. إنّ AuthGuard ليس سوى حارس NestJS مدعوم بـ Passport — مفهوم CanActivate نفسه من المرحلة الثالثة. الاستراتيجية تزوّد منطق التحقّق؛ والحارس يشغّله.

الخلاصة

تُنظّم Passport (عبر @nestjs/passport) المصادقة في استراتيجيات. تتحقّق الاستراتيجية المحلية من البريد + كلمة المرور: تفحص AuthService.validateUser() كلمة مرور مُجزّأة، وتستدعيها LocalStrategy.validate()، ويحمي AuthGuard('local') مسار الدخول مُرفِقًا المستخدم بالطلب. جزّئ كلمات المرور دائمًا. بعد التحقّق من مستخدم، تحتاج رمزًا لإبقائه مُسجَّل الدخول — وهذا JWT، تاليًا.