احراز هویت با JWT، Refresh Token و RBAC در NestJS
طراحی access/refresh، چرخش توکن، لغو نشست، و کنترل دسترسی نقش/مجوز بدون پاشیدن منطق امنیت در کنترلرها.
علی مرتضوی
بنیانگذار پارادایس کد
Access کوتاه، Refresh محافظتشده
Access token باید عمر کوتاه داشته باشد (دقایق، نه روزها) و فقط claimهای لازم را حمل کند: `sub`، `tenantId`، نقشها یا نسخهٔ مجوز. Refresh token عمر بلندتر دارد اما باید در ذخیرهسازی امنتر بماند—httpOnly cookie با Secure/SameSite مناسب، یا ذخیرهٔ سختگیرانهٔ موبایل—و در سرور قابل لغو باشد.
JWT بیوضعیت برای access خوب است؛ برای refresh، بدون رهگیری سمت سرور (جای اثر، خانوادهٔ توکن، یا لیست لغو) نمیتوانید سرقت توکن را مهار کنید.
چرخش Refresh و تشخیص سرقت
هر بار استفاده از refresh، توکن قبلی را باطل و توکن جدید صادر کنید (rotation). اگر توکن باطلشده دوباره استفاده شد، کل خانوادهٔ نشست را باطل کنید—این سیگنال کلاسیک replay/سرقت است. این الگو از «refresh یکبار برای همیشه» بهمراتب امنتر است.
메타دیتای نشست را نگه دارید: user agent، IP تقریبی، زمان ساخت، آخرین استفاده. به کاربر امکان «خروج از همه دستگاهها» بدهید؛ این فیچر امنیتی است نه لوکس تنظیمات.
RBAC و مجوزهای واقعی محصول
نقش Alone کافی نیست. نقش را به مجموعهای از permissionهای پایدار نگاشت کنید (`invoice:read`, `invoice:write`). در Nest، Guarding را روی permission بسازید نه روی رشتهٔ نقش سختکدشده در هر کنترلر. منبع حقیقت مجوز میتواند JWT نسخهٔ کوتاه + کش، یا خواندن کنترلشده از دیتابیس برای عملیات حساس باشد.
برای SaaS چندمستأجری، نقش داخل تننت معنا دارد. هرگز مجوز را بدون `tenantId` ارزیابی نکنید. تست IDOR باید بخشی از CI امنیتی باشد.
لایهٔ Nest: ماژول Auth تمیز
Strategyهای Passport/JWT را نازک نگه دارید: استخراج توکن، اعتبار امضا، بارگذاری context کاربر. منطق کسبوکار ورود، قفل حساب، و audit در سرویس دامنه بماند. Rate limit روی login/refresh/forgot-password اجباری است.
خطاها را یکدست کنید تا oracle کمتری بدهید: «ایمیل یا رمز نادرست» بهجای افشای وجود کاربر در همه مسیرها—با تعادل UX که محصولتان میپذیرد. برای مسیرهای حساس، logging امنیتی بدون رمز و بدون PII اضافی داشته باشید.
ذخیرهٔ توکن در وب و موبایل
در وب SPA، access در حافظه و refresh در httpOnly cookie الگوی رایجی است که XSS را از دزدیدن refresh سختتر میکند—به شرط CSRF protection متناسب. localStorage برای refresh معمولاً اشتباه است. در موبایل از secure storage سیستم عامل استفاده کنید.
CORS و cookie domain را حداقلی تنظیم کنید. دامنهٔ خیلی باز، مدل امنیتی را بیاثر میکند.
لغو، تغییر رمز و رویدادهای امنیتی
تغییر رمز، ارتقای نقش، یا تشخیص ناهنجاری باید نشستها را باطل یا access را زودتر منقضی کند (نسخهٔ `tokenVersion` روی کاربر). فقط تکیه به expiry access کافی نیست.
برای عملیات حساس (تغییر ایمیل، خروج پول)، re-auth یا step-up با عامل دوم را در نظر بگیرید. RBAC دسترسی را محدود میکند؛ حساسیت عملیات لایهٔ اضافه میخواهد.
چکلیست قبل از پروداکشن
الگوریتم امضای مدرن، چرخش کلید، secrets در vault/env امن، rotation تستشده، و مسیر logout سراسری را بررسی کنید. تست نفوذ روی auth را به اندازهٔ فیچرهای تجاری جدی بگیرید.
امنیت احراز هویت نقطهٔ برند است: یک باگ اینجا اعتماد کل محصول را میشکند. در پیادهسازیهای جدی—از جمله کارهایی که در پارادایس کد برای محصولات حساس انجام میشود—این لایه قبل از زیباسازی UI قفل میشود.
سؤالات متداول
عمر مناسب access token چقدر است؟
معمولاً ۵ تا ۱۵ دقیقه برای وب. کوتاهتر امنتر است اگر refresh و UX شما روان باشد.
آیا JWT برای refresh کافی است بدون ذخیره سرور؟
خیر برای مدل امن. حداقل به رهگیری/لغو سمت سرور یا خانوادهٔ توکن نیاز دارید.
Permission را در JWT بگذاریم یا هر بار از DB بخوانیم؟
برای مسیرهای پرتکرار، claim فشرده یا کش با نسخه؛ برای عملیات حساس، چک تازه از منبع حقیقت.
SameSite=Lax کافی است؟
بستگی به مدل کراسسایت شما دارد. برای cookieهای حساس اغلب Strict یا Lax با CSRF token صریح ترکیب میشود. نیاز محصول را صریح طراحی کنید.
دانش و مقالات
نیاز به اجرای همین مفاهیم در محصولتان دارید؟
پارادایس کد از مشاوره تا پیادهسازی کامل کنار شماست.