توکنهای وب JSON (JWT) به استاندارد احراز هویت بدون حالت در برنامههای وب مدرن تبدیل شدهاند. با این حال، راحتی آنها اغلب منجر به پیکربندیهای امنیتی بحرانی میشود. از آنجا که JWTها خودکفا هستند، هر سروری که آنها را تأیید میکند، بدون بررسی پایگاه داده مرکزی، به بار (payload) اعتماد میکند. این انتخاب طراحی از توسعهدهندگان میخواهد که در مورد نحوه تولید، انتقال و اعتبارسنجی توکنها بسیار دقیق باشند. این راهنما، شیوههای امنیتی ضروری را برای جلوگیری از آسیبپذیریهای رایج مانند رهگیری توکن، حملات سردرگمی الگوریتم و دسترسی غیرمجاز ترسیم میکند.
1. استفاده از زمانهای انقضا کوتاه و توکنهای تازهسازی
رایجترین اشتباهی که توسعهدهندگان مرتکب میشوند، صدور JWTها با زمانهای انقضای طولانی، مانند ۲۴ ساعت یا بیشتر است. اگر توکنی دزدیده شود، مهاجم تا پایان کامل مدت اعتبار آن به سیستم دسترسی خواهد داشت. به جای این کار، از یک توکن دسترسی کوتاهعمر (مثلاً ۱۵ دقیقه) در ترکیب با یک توکن تازهسازی بلندعمرتر استفاده کنید.
توکن دسترسی درخواستهای فوری API را مدیریت میکند، در حالی که توکن تازهسازی که بهطور ایمن در سمت سرور ذخیره میشود، برای صدور توکنهای دسترسی جدید استفاده میشود. این کار پنجره فرصت برای مهاجم را محدود میکند. اگر مجبور به صدور توکنهای بلندعمر هستید، اطمینان حاصل کنید که مکانیزمی برای سیاهچال کردن توکنهای آسیبدیده در یک کش توزیعشده مانند Redis دارید.
2. اجبار به استفاده از HTTPS و کوکیهای HttpOnly
هرگز JWTها را در URL یا به عنوان پارامترهای کوئری منتقل نکنید، زیرا ممکن است در لاگهای دسترسی سرور یا تاریخچه مرورگر ثبت شوند. برای برنامههای وب، ذخیره توکن در یک کوکی httpOnly و Secure ایمنترین رویکرد است. این کار از حملات اسکریپتنویسی سمت کلاینت (XSS) برای خواندن توکن از طریق جاوااسکریپت جلوگیری میکند. برای برنامههای موبایل یا بومی، جایی که کوکیها کمتر عملی هستند، توکن را در ذخیرهسازی ایمن (مانند Keychain iOS یا Keystore Android) ذخیره کنید و همیشه از HTTPS استفاده کنید.
3. قفل کردن الگوریتم برای جلوگیری از حملات سردرگمی
یک آسیبپذیری قابل توجه زمانی رخ میدهد که سرور هر الگوریتمی را که در هدر JWT ارائه میشود، بپذیرد. مهاجمان میتوانند الگوریتم را از RS256 (غیرمتقارن) به HS256 (متقارن) تغییر دهند و توکن را با کلید عمومی امضا کنند، در حالی که سرور ممکن است اشتباهاً از آن به عنوان کلید مخفی استفاده کند. برای جلوگیری از این موضوع، صریحاً تأیید کنید که الگوریتم در هدر توکن با الگوریتم مورد انتظار مطابقت دارد.
import jwt from 'jsonwebtoken';
const verifyToken = (token, publicKey) => {
try {
// Explicitly set the algorithms allowed
const decoded = jwt.verify(token, publicKey, {
algorithms: ['RS256']
});
return decoded;
} catch (err) {
// Handle invalid tokens or wrong algorithms
throw new Error('Token verification failed');
}
};
4. چرخش منظم کلیدهای امضا
اگر کلید امضای شما آسیب ببیند، تمام توکنهای صادرشده قبلی تا زمان انقضای آنها معتبر باقی میمانند. برای کاهش این خطر، چرخش کلید را پیادهسازی کنید. از شناسههای کلید (kid) در هدر JWT برای شناسایی کلیدی که توکن را امضا کرده استفاده کنید. این کار به شما امکان میدهد چندین کلید عمومی را توزیع کرده و کلیدهای مخفی را بدون باطل کردن تمام جلسات موجود چرخش دهید. سیستمهای مدیریت کلید خودکار مانند HashiCorp Vault میتوانند به مدیریت ایمن این فرآیند کمک کنند.
5. اعتبارسنجی سختگیرانه ادعاها
همیشه ادعاهای iss (صادرکننده) و aud (مخاطب) را اعتبارسنجی کنید. بدون این کار، توکنی که توسط سرویس A صادر شده است، ممکن است اگر هر دو از کلید امضای یکسان استفاده کنند، برای دسترسی به سرویس B استفاده شود. اطمینان حاصل کنید که منطق اعتبارسنجی شما این ادعاها را با مقادیر مورد انتظار برای محیط برنامه خاص خود بررسی میکند.
نتیجهگیری
امنیت احراز هویت JWT فقط درباره کدگذاری و امضا نیست؛ بلکه درباره مدیریت کل چرخه عمر توکن است. با پیادهسازی زمانهای انقضای کوتاه، استفاده از مکانیزمهای ذخیرهسازی ایمن، قفل کردن الگوریتمها و چرخش کلیدها، سطح حمله را بهطور قابلتوجهی کاهش میدهید. همیشه JWT را به عنوان یک اعتبارنامه حامل (bearer credential) در نظر بگیرید—اگر در دست اشتباهی قرار گیرد، دسترسی کامل را اعطا میکند. این شیوهها را بپذیرید تا سیستمهای احراز هویت محکم و ایمنی بسازید که کاربران و ذینفعان میتوانند به آن اعتماد کنند.