Application Security

تقویت API شما: پیاده‌سازی JWT با توکن‌های دسترسی کوتاه‌مدت و چرخش توکن تازه‌سازی

در فضای امنیتی امروزی برنامه‌های وب، بحث بین توکن‌های وب JSON (JWT) و احراز هویت مبتنی بر جلسه همچنان در حال تحول است. اگرچه JWTها بی‌حالت بودن و مقیاس‌پذیری را ارائه می‌دهند، اما با خطرات ذاتی، عمدتاً متمرکز بر سرقت توکن و دشواری لغو آن‌ها همراه هستند. بهترین روش استاندارد صنعت برای کاهش این خطرات، یک استراتژی دو توکنی است: استفاده از توکن‌های دسترسی بسیار کوتاه‌مدت همراه با توکن‌های تازه‌سازی که به‌طور امن مدیریت و چرخش می‌شوند. این رویکرد پنجره فرصت برای مهاجمان را به حداقل می‌رساند و در عین حال تجربه کاربری روانی را حفظ می‌کند.

آسیب‌پذیری توکن‌های با عمر طولانی

پیاده‌سازی‌های سنتی JWT اغلب زمان انقضا (exp) را چندین ساعت یا حتی چند روز تنظیم می‌کنند. اگرچه این کار راحت است، اما یک آسیب‌پذیری امنیتی قابل توجه ایجاد می‌کند. اگر یک توکن دسترسی از طریق حملات Scripting بین سایتی (XSS)، شنود شبکه یا یک کلاینت نفوذ کرده استراق شود، مهاجم در آن کل پنجره زمانی برای جعل هویت کاربر فرصت دارد. برخلاف جلسات سمت سرور که می‌توانند بلافاصله در سرور نامعتبر شناخته شوند، JWTها خودمختار هستند. لغو یک توکن با عمر طولانی نیاز به یک «لیست مسدودی» یا یک حافظه پنهان توزیع‌شده (مانند Redis) برای بررسی اعتبار دارد که این امر تأخیر و پیچیدگی را افزایش می‌دهد.

با کاهش عمر توکن دسترسی به چند دقیقه (مثلاً ۱۵ دقیقه)، سطح حمله به شدت کاهش می‌یابد. حتی اگر یک توکن دزدیده شود، تقریباً بلافاصله بی‌استفاده می‌شود. با این حال، این موضوع یک مشکل جدید ایجاد می‌کند: چگونه کاربران بدون وارد کردن مداوم اعتبارنامه‌ها وارد سیستم بمانند؟ اینجاست که توکن‌های تازه‌سازی وارد عمل می‌شوند.

معرفی چرخش توکن تازه‌سازی

یک توکن تازه‌سازی یک اعتبارنامه با عمر طولانی است که برای دریافت توکن‌های دسترسی جدید استفاده می‌شود. بهبود امنیتی حیاتی در اینجا چرخش است. در یک پیاده‌سازی ساده، یک توکن تازه‌سازی تا زمان انقضای آن استفاده مجدد می‌شود. این موضوع آن را در برابر حملات تکرار توکن آسیب‌پذیر می‌کند؛ یک بار که دزدیده شود، مهاجم می‌تواند به طور مداوم از آن برای تولید توکن‌های دسترسی جدید استفاده کند.

با چرخش، هر بار که یک توکن تازه‌سازی برای دریافت یک توکن دسترسی جدید استفاده می‌شود، یک توکن تازه‌سازی کاملاً جدید تولید و صادر می‌گردد. توکن تازه‌سازی قدیمی بلافاصله نامعتبر شناخته می‌شود. این کار یک «هدف متحرک» برای مهاجمان ایجاد می‌کند. اگر مهاجم توکن تازه‌سازی A را بدزدد و از آن استفاده کند، سرور توکن دسترسی B و توکن تازه‌سازی C را صادر می‌کند و همزمان توکن A را در لیست سیاه قرار می‌دهد. مهاجم محروم می‌شود، در حالی که کاربر قانونی به طور شفاف اعتبارنامه‌های جدید را در پس‌زمینه دریافت می‌کند.

استراتژی پیاده‌سازی

پیاده‌سازی این الگو نیاز به مدیریت دقیق چرخه عمر توکن دارد. در زیر یک مثال مفهومی Node.js/Express که منطق چرخش را نشان می‌دهد، آورده شده است. نکته کلیدی این است که توکن تازه‌سازی ذخیره شده در پایگاه داده شما باید برای هر جلسه کاربر منحصر به فرد باشد و در هر رویداد احراز هویت موفق تغییر کند.

// کد شبه برای منطق چرخش توکن
const jwt = require('jsonwebtoken');
const crypto = require('crypto');

// 1. کاربر وارد سیستم می‌شود یا توکن را تازه می‌کند
async function handleTokenRequest(refreshToken) {
  // یافتن توکن تازه‌سازی در پایگاه داده
  const storedTokenData = await db.findRefreshToken(refreshToken);

  if (!storedTokenData || jwt.verify(refreshToken, process.env.REFRESH_SECRET) === false) {
    throw new Error('توکن تازه‌سازی نامعتبر');
  }

  // 2. چرخش توکن تازه‌سازی
  // تولید یک توکن تازه‌سازی جدید
  const newRefreshToken = jwt.sign(
    { sub: storedTokenData.userId, jti: crypto.randomUUID() }, 
    process.env.REFRESH_SECRET, 
    { expiresIn: '7d' }
  );

  // 3. نامعتبر کردن توکن قدیمی در پایگاه داده
  // مرحله حیاتی: توکن قدیمی اکنون بی‌استفاده است
  await db.invalidateToken(storedTokenData.jti);

  // 4. ذخیره توکن جدید با یک JTI منحصر به فرد برای چرخش بعدی
  await db.saveRefreshToken(storedTokenData.userId, newRefreshToken, crypto.randomUUID());

  // 5. صدور یک توکن دسترسی کوتاه‌مدت
  const accessToken = jwt.sign(
    { userId: storedTokenData.userId }, 
    process.env.ACCESS_SECRET, 
    { expiresIn: '15m' }
  );

  return { accessToken, newRefreshToken };
}

بهترین شیوه‌ها برای امنیت بیشتر

  • ذخیره‌سازی امن: توکن‌های دسترسی باید فقط در حافظه ذخیره شوند. توکن‌های تازه‌سازی باید در کوکی‌های httpOnly، secure و SameSite=Strict ذخیره شوند تا از سرقت از طریق XSS جلوگیری شود. هرگز توکن‌ها را در localStorage ذخیره نکنید.
  • JTI منحصر به فرد: همیشه یک ادعای شناسه JWT (jti) را در توکن‌های تازه‌سازی خود گنجانید. این به شما امکان می‌دهد توکن‌های خاص را به طور منحصر به فرد شناسایی و لغو کنید، که برای عملکرد صحیح مکانیسم چرخش ضروری است.
  • پنجره لغزنده: در نظر بگیرید که یک پنجره انقضای لغزنده را برای توکن‌های تازه‌سازی پیاده‌سازی کنید. اگر کاربر فعال باشد، عمر توکن تازه‌سازی او را گسترش دهید، اما حداکثر عمر مطلق را محدود کنید (مثلاً ۷ روز یا ۳۰ روز) تا احراز هویت دوره‌ای را اجبار کنید.
  • تشخیص سوءاستفاده: برای جلسات همزمان متعدد یا تغییرات IP مشکوک نظارت کنید. اگر یک توکن تازه‌سازی از یک دستگاه جدید استفاده شود، در نظر بگیرید که نیاز به تأیید اضافی یا خروج از تمام جلسات دیگر باشد.

نتیجه‌گیری

پیاده‌سازی JWTهای کوتاه‌مدت با چرخش توکن تازه‌سازی تنها یک مورد در چک‌لیست امنیت نیست؛ بلکه یک تصمیم معماری بنیادین است که امنیت و قابلیت استفاده را متعادل می‌کند. با به حداقل رساندن عمر توکن‌های دسترسی فعال و اطمینان از اینکه توکن‌های تازه‌سازی پس از یک بار استفاده قابل استفاده مجدد نیستند، برنامه خود را به طور قابل توجهی در برابر سرقت توکن و حملات تکرار ایمن می‌کنید. اگرچه این رویکرد پیچیدگی را به جریان احراز هویت شما اضافه می‌کند، اما کاهش خطر چشمگیر است. برای هر برنامه‌ای که داده‌های حساس را مدیریت می‌کند، این الگو دیگر اختیاری نیست— بلکه ضروری است.

Share: