TrendVidStream تمام پشته احراز هویت خود را به یک سیستم توکن بازنشانی چرخشی (rotating-refresh-token) منتقل کرد که در لحظه استفاده مجدد از یک توکن سرقت‌شده، آن را شناسایی می‌کند. این تغییر، یک JWT ۳۰ روزه‌ای را که زمانی به مهاجم اجازه می‌داد آزادانه فعالیت کند، به یک اعتبارنامه کوتاه‌مدت تبدیل کرد که بلافاصله باعث مسدود شدن دسترسی می‌شود.

یک رخنه امنیتی واحد باعث این تغییر شد: یک SDK شریک، یک JWT ۳۰ روزه را به صورت متن ساده (plain text) ذخیره کرده بود؛ مهاجم آن را استخراج کرد و از کشور دیگری بازپخش (replay) نمود، و تنها راه حل، چرخاندن کلید امضا بود—عملیاتی که باعث خروج تمام کاربران از سیستم شد. این حادثه امنیت توکن‌های شرکت را بازتعریف کرد و اکنون قدرت بخشنده سرویس پخش ویدئویی آن است.

چرا مدل قدیمی شکست خورد

JWTها (JSON Web Tokens) بلوک‌های امضا شده و خودکافی هستند که به سرور اجازه می‌دهند بدون جستجو در پایگاه داده، یک درخواست را تأیید کند. این راحتی، هزینه‌ای را به همراه دارد: اگر توکن هفته‌ها اعتبار داشته باشد، سرقت آن به معنای دسترسی هفته‌ها برای مهاجم است. در آن رخنه، توکن سرقت‌شده تا پایان اعتبار ۳۰ روزه خود معتبر باقی ماند، زیرا راهی برای ابطال زودهنگام آن وجود نداشت.

چرخاندن کلید امضا تنها راه جهانی برای ابطال تمام توکن‌هاست، اما باعث می‌شود هر کاربر مجبور به ورود مجدد شود که منجر به اختلال در سرویس و کاهش اعتماد می‌شود. نقص مشکل در خودِ JWT نبود، بلکه در تکیه بر یک اعتبارنامه واحد و طولانی‌مدت بود.

خلاصه طراحی جدید

TrendVidStream اکنون دو نوع توکن صادر می‌کند:

  • Access tokens – معتبر برای ۱۵ دقیقه؛ این توکن‌ها مجوزهای مورد نیاز برای هر فراخوانی API را با خود دارند.
  • Refresh tokens – توکن‌های تک‌بار مصرف که یک توکن دسترسی کوتاه‌مدت را با یک جفت جدید تعویض می‌کنند.

وقتی کلاینت یک توکن بازنشانی را ارائه می‌دهد، سرور:

  1. امضا و ادعاهای (claims) توکن را تأیید می‌کند.
  2. بررسی می‌کند که آیا توکن قبلاً استفاده شده است یا خیر.
  3. اگر بررسی موفقیت‌آمیز بود، یک توکن بازنشانی کاملاً جدید و یک توکن دسترسی ۱۵ دقیقه‌ای تازه صادر می‌کند.
  4. توکن بازنشانی قدیمی را به عنوان «استفاده شده» علامت‌گذاری می‌کند.

اگر مرحله ۲ با شکست مواجه شود—یعنی همان توکن برای بار دوم ظاهر شود—سرور آن را به عنوان سیگنال سرقت در نظر گرفته و کل «خانواده» توکن‌های مرتبط با آن نشست (session) ورود را باطل می‌کند. هم قربانی و هم مهاجم مجبور به ورود مجدد می‌شوند و بدین ترتیب مدت زمان رخنه قطع می‌شود.

ردیابی خانواده‌های توکن

به جای اینکه با هر توکن به عنوان یک رکورد مجزا برخورد شود، سیستم آن‌ها را در قالب خانواده‌هایی گروه‌بندی می‌کند که با ورود کاربر شروع می‌شوند. هر چرخش، عضو جدیدی برای آن خانواده ایجاد می‌کند. طرحواره (schema) SQLite که در محیط عملیاتی استفاده می‌شود، موارد زیر را ذخیره می‌کند:

  • family_id – یک شناسه ثابت برای کل نشست.
  • token_id – یک شناسه منحصربه‌فرد برای هر توکن بازنشانی.
  • generation – یک شمارنده که برای عیب‌یابی مفید است.
  • used_at – برچسب زمانی زمانی که توکن استفاده شده است.
  • revoked – یک پرچم (flag) که در صورت فعال شدن، کل خانواده را غیرفعال می‌کند.

هنگام تشخیص رویداد استفاده مجدد، پرچم revoked برای آن family_id تنظیم می‌شود و بلافاصله تمام توکن‌های متعلق به نشست آسیب‌دیده را باطل می‌کند. این کار یک ربایش بی‌صدا را به یک هشدار با سیگنال بالا تبدیل می‌کند که در گزارش‌های سیستم (logs) ظاهر می‌شود.

سه قانون پیاده‌سازی برای قابل اعتماد نگه داشتن سیستم

  1. ابتدا امضا را تأیید کنید اگر سرور قبل از تأیید امضا، وضعیت «قبلاً استفاده شده؟» را بررسی کند، مهاجم می‌تواند شناسه‌های توکن را حدس زده و باعث ابطال‌های دسته‌جمعی شود. تأیید اصالت در مرحله اول، از حملات منع سرویس (DoS) غیرضروری جلوگیری می‌کند.

  2. یک بازه زمانی مجاز (grace window) در نظر بگیرید اپلیکیشن‌های موبایل اغلب هنگام انقضای توکن، دو درخواست بازنشانی را با فاصله بسیار کم ارسال می‌کنند. اگر سرور بیش از حد سخت‌گیر باشد، درخواست دوم به عنوان استفاده مجدد علامت‌گذاری شده و باعث خروج کاربر قانونی از سیستم می‌شود. چند ثانیه زمان ذخیره (buffer) اجازه می‌دهد که یک توکن «استفاده شده» همچنان یک جفت جدید دریافت کند و شرایط رقابتی (race conditions) را مدیریت کند.

  3. کل جریان را در یک تراکنش با قفل کردن ردیف (row locking) قرار دهید بدون اتمیسیته (atomicity)، دو درخواست همزمان ممکن است هر دو تصور کنند که اولین بار است از یک توکن استفاده می‌کنند، که منجر به صدور توکن‌های بازنشانی تکراری و شکستن تضمین تک‌بار مصرف می‌شود. یک تراکنش پایگاه داده که ردیف توکن را قفل می‌کند، تضمین می‌کند که تنها یک درخواست موفق شود.

نتیجه‌گیری: با تک‌بار مصرف کردن توکن‌های بازنشانی و نظارت بر استفاده مجدد از آن‌ها، یک سیستم می‌تواند هر اعتبارنامه سرقت‌شده را به یک زنگ خطر تبدیل کند و بدون مجبور کردن همه کاربران به خروج از سیستم، از آن‌ها محافظت کند.