ToolDeck

JWT

2 ابزار

مبانی امنیت وب

امنیت وب به معنای حفاظت از برنامه‌های وب و API‌ها در برابر دسترسی غیرمجاز، نشت داده و حملات است. برنامه‌های مدرن از احراز هویت (اثبات هویت)، مجوزدهی (اثبات دسترسی‌ها) و رمزنگاری برای اعمال مرزهای امنیتی استفاده می‌کنند.

JSON Web Tokens (JWT) مکانیزم غالب احراز هویت بدون وضعیت در توسعه وب مدرن هستند. درک نحوه کارکرد JWT‌ها — شامل ساختار، الگوریتم‌های امضا و آسیب‌پذیری‌ها — برای ساخت API‌ها و برنامه‌های امن ضروری است.

JSON Web Tokens (JWT)

JWT روشی فشرده و URL-safe برای نمایش ادعاها بین دو طرف است. از سه بخش Base64url-encoded جدا شده با نقطه تشکیل شده است. JWT‌ها می‌توانند بدون جستجو در پایگاه داده تأیید شوند زیرا امضا کل توکن را پوشش می‌دهد.

سه بخش یک JWT

Header

حاوی متادیتای توکن است: الگوریتم امضا (alg) و نوع توکن (typ). همیشه JSON با رمزگذاری Base64url است. انتخاب الگوریتم در اینجا بر امنیت کل توکن تأثیر می‌گذارد.

رمزگذاری‌شده
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
رمزگشایی‌شده
{
  "alg": "HS256",
  "typ": "JWT"
}
Payload

حاوی ادعاها است: اطلاعاتی درباره کاربر و متادیتای اضافی. همچنین JSON با رمزگذاری Base64url است. هر کسی می‌تواند این بخش را رمزگشایی کند — داده‌های payload رمزگذاری نشده‌اند، فقط امضا شده‌اند.

رمزگذاری‌شده
eyJzdWIiOiJ1c2VyXzEyMyIsInJvbGUiOiJhZG1pbiIsImV4cCI6MTcxNzIwMDAwMH0
رمزگشایی‌شده
{
  "sub": "user_123",
  "role": "admin",
  "exp": 1717200000
}
Signature

یک امضای رمزنگاری بر روی header و payload رمزگذاری‌شده است. تأیید این امضا تضمین می‌کند که توکن دستکاری نشده است. کلید مخفی (HMAC) یا کلید خصوصی (RSA/ECDSA) هرگز در توکن گنجانده نمی‌شود.

رمزگذاری‌شده
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
رمزگشایی‌شده
HMACSHA256(
  base64url(header) + "." +
  base64url(payload),
  secret
)

ادعاهای استاندارد JWT

مشخصات JWT نام‌های ادعای استاندارد را تعریف می‌کند. استفاده از آن‌ها قابلیت همکاری بین کتابخانه‌ها و سرویس‌های مختلف JWT را تضمین می‌کند:

ادعانامتوضیح
issIssuerاصلی که توکن را صادر کرده شناسایی می‌کند (مثلاً URL سرور احراز هویت شما)
subSubjectاصلی که موضوع توکن است شناسایی می‌کند (مثلاً شناسه کاربر)
audAudienceگیرندگانی که توکن برای آن‌ها در نظر گرفته شده را شناسایی می‌کند (مثلاً URL API شما)
expExpirationزمان انقضای توکن به صورت Unix timestamp — بعد از این زمان توکن دیگر معتبر نیست
nbfNot Beforeزمان فعال‌سازی توکن به صورت Unix timestamp — قبل از این زمان توکن نباید پذیرفته شود
iatIssued Atزمان صدور توکن به صورت Unix timestamp — برای تعیین عمر توکن استفاده می‌شود
jtiJWT IDشناسه یکتا برای توکن، برای جلوگیری از حملات replay توکن استفاده می‌شود

الگوریتم‌های امضا

الگوریتم امضا در header JWT اعلام می‌شود. انتخاب الگوریتم مناسب برای موارد استفاده‌تان برای امنیت حیاتی است:

HS256 / HS384 / HS512متقارن (HMAC)

از یک کلید مخفی مشترک هم برای امضا و هم برای تأیید استفاده می‌کند. پیاده‌سازی ساده اما نیاز دارد همه تأییدکنندگان کلید مخفی را بدانند.

چه زمانی استفاده کنید: سرویس‌های داخلی که تمام طرف‌ها را کنترل می‌کنید. هرگز در مواردی که اشخاص ثالث نیاز به تأیید توکن دارند استفاده نکنید.
RS256 / RS384 / RS512نامتقارن (RSA)

از کلید خصوصی برای امضا و کلید عمومی برای تأیید استفاده می‌کند. کلید خصوصی هرگز سرور احراز هویت را ترک نمی‌کند.

چه زمانی استفاده کنید: معماری‌های میکروسرویس، تأیید توکن توسط اشخاص ثالث، OAuth2 و OpenID Connect.
ES256 / ES384 / ES512نامتقارن (ECDSA)

مانند RSA اما با کلیدهای کوچک‌تر و امضای سریع‌تر. امنیت معادل با عملکرد بهتر ارائه می‌دهد.

چه زمانی استفاده کنید: برنامه‌های موبایل و IoT که عملکرد اهمیت دارد. جایگزین مدرن RSA.
"alg": "none"بدون امضا — خطرناک

اصلاً هیچ امضایی ندارد. توکنی با alg:none هیچ تضمین یکپارچگی ندارد و می‌تواند توسط هر کسی جعل شود.

چه زمانی استفاده کنید: هرگز در محیط تولید استفاده نکنید. برخی کتابخانه‌های JWT به طور تاریخی alg:none را می‌پذیرفتند که به آسیب‌پذیری‌های حیاتی منجر شد.

جریان‌های احراز هویت

اعطای رمز عبور (مستقیم)
  1. 1.کاربر نام کاربری و رمز عبور را به endpoint ورود ارسال می‌کند
  2. 2.سرور اعتبارنامه‌ها را در برابر پایگاه داده کاربران اعتبارسنجی می‌کند
  3. 3.سرور یک JWT با ادعاهای کاربر و زمان انقضا امضا می‌کند
  4. 4.کلاینت JWT را ذخیره می‌کند (localStorage، کوکی یا حافظه)
  5. 5.کلاینت JWT را در header Authorization: Bearer برای درخواست‌های بعدی ارسال می‌کند
کد مجوز + PKCE (OAuth2)
  1. 1.کلاینت کاربر را با code challenge به سرور مجوز هدایت می‌کند
  2. 2.کاربر احراز هویت می‌کند و برنامه کلاینت را مجاز می‌کند
  3. 3.سرور احراز هویت با یک کد مجوز یک‌بار مصرف بازمی‌گردد
  4. 4.کلاینت کد + verifier را با توکن‌های دسترسی و refresh مبادله می‌کند
  5. 5.کلاینت از توکن دسترسی برای فراخوانی‌های API و از refresh token برای تجدید استفاده می‌کند

آسیب‌پذیری‌های رایج JWT

JWT‌ها وقتی به درستی پیاده‌سازی شوند امن هستند. اینها رایج‌ترین اشتباهات پیاده‌سازی هستند که به آسیب‌پذیری‌های امنیتی منجر می‌شوند:

سردرگمی الگوریتم (alg:none)بحرانی

برخی کتابخانه‌ها توکن‌هایی با alg:none (بدون امضا) می‌پذیرند. یک مهاجم می‌تواند payload را تغییر داده و alg را به none تنظیم کند تا هر JWT را جعل کند. همیشه الگوریتم مجاز را به صراحت مشخص و اعتبارسنجی کنید.

سردرگمی HS256 / RS256بحرانی

اگر یک کتابخانه انتظار تأیید RS256 را داشته باشد اما HS256 را هم بپذیرد، یک مهاجم می‌تواند با استفاده از کلید عمومی به عنوان secret در HMAC توکنی امضا کند. کتابخانه آن را با موفقیت تأیید می‌کند. همیشه الگوریتم مورد انتظار را مشخص نگه دارید.

فقدان اعتبارسنجی انقضابالا

یک JWT بدون ادعای exp، یا کدی که exp را بررسی نمی‌کند، اجازه می‌دهد توکن‌ها پس از خروج یا مسدود شدن کاربر به‌طور نامحدود استفاده شوند. همیشه زمان‌های انقضای کوتاه تنظیم کنید و ادعای exp را اعتبارسنجی کنید.

داده‌های حساس در payloadبالا

payload های JWT با Base64 رمزگذاری شده‌اند، نه رمزگذاری واقعی. هر کسی که یک JWT را دریافت کند می‌تواند payload را رمزگشایی و بخواند. هرگز رمز عبور، شماره کارت اعتباری یا سایر اسرار را در ادعاهای JWT ذخیره نکنید.

کلیدهای مخفی ضعیف (HS256)متوسط

JWT‌های امضاشده با HMAC با اسرار کوتاه یا قابل پیش‌بینی می‌توانند به صورت آفلاین brute-force شوند. یک مهاجم که یک JWT را به دست آورد می‌تواند میلیاردها کلید در ثانیه امتحان کند. از اسرار تصادفی رمزنگاری با حداقل ۲۵۶ بیت استفاده کنید.

فقدان تأیید امضامتوسط

قبول کردن JWT بدون بررسی امضا یعنی اعتماد کامل به محتوای payload. این یک باگ حیاتی است که به هر کاربری اجازه می‌دهد ادعاهای دلخواه بسازد. همیشه قبل از اعتماد به هر ادعایی امضا را تأیید کنید.

سؤالات متداول

آیا JWT‌ها رمزگذاری شده‌اند؟

JWT‌های استاندارد (JWS — JSON Web Signature) امضا شده‌اند اما رمزگذاری نشده‌اند. payload با Base64url رمزگذاری شده که به سادگی قابل برگشت است. هر کسی که یک JWT داشته باشد می‌تواند محتوای آن را بخواند. JWE (JSON Web Encryption) رمزگذاری واقعی ارائه می‌دهد اما بسیار کمتر رایج است.

یک JWT چه مدت باید معتبر باشد؟

توکن‌های دسترسی باید کوتاه‌مدت باشند: ۵ تا ۶۰ دقیقه معمول است. توکن‌های طولانی‌مدت خطرناک هستند زیرا بدون یک لیست مسدود توکن نمی‌توانند باطل شوند. از refresh token‌ها (طولانی‌مدت‌تر، با ذخیره‌سازی امن) برای دریافت توکن‌های دسترسی جدید استفاده کنید.

JWT‌ها را در مرورگر کجا ذخیره کنم؟

کوکی‌های HttpOnly امن‌ترین گزینه هستند — برای JavaScript غیرقابل دسترسی هستند و از سرقت XSS جلوگیری می‌کنند. localStorage در برابر حملات XSS آسیب‌پذیر است اما از CSRF جلوگیری می‌کند. حافظه (متغیر JavaScript) امن‌ترین است اما پس از reload صفحه باقی نمی‌ماند. هیچ گزینه کاملی وجود ندارد.

آیا می‌توانم یک JWT را قبل از انقضا باطل کنم؟

نه بدون وضعیت سمت سرور. ماهیت بدون وضعیت JWT‌ها به این معناست که سرور نمی‌تواند آن‌ها را باطل کند. راه‌حل‌ها: زمان‌های انقضای کوتاه، یک لیست مسدود توکن (Redis)، چرخش refresh token‌ها، یا تغییر به توکن‌های session مات برای عملیات حساس.

تفاوت JWT و کوکی‌های session چیست؟

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

چه ادعاهایی باید در JWT قرار دهم؟

حداقل: sub (شناسه کاربر)، exp (انقضا) و iat (زمان صدور). برای راه‌اندازی‌های چند سرویسه iss (صادرکننده) اضافه کنید. payload‌ها را کوچک نگه دارید — JWT‌ها با هر درخواست ارسال می‌شوند. داده‌های حساس یا آبجکت‌های بزرگ پروفایل را در ادعاها قرار ندهید.

آیا RS256 بهتر از HS256 است؟

RS256 (نامتقارن) برای اکثر سیستم‌های تولید بهتر است زیرا فقط سرور احراز هویت به کلید خصوصی نیاز دارد. سرویس‌های متعدد می‌توانند با استفاده از کلید عمومی توکن‌ها را بدون اشتراک‌گذاری secret تأیید کنند. HS256 ساده‌تر است اما نیاز دارد همه تأییدکنندگان secret مشترک را بدانند.

PKCE چیست و چرا مهم است؟

PKCE (Proof Key for Code Exchange) یک افزونه برای جریان کد مجوز OAuth2 است که از حملات دزدیدن کد مجوز جلوگیری می‌کند. برای کلاینت‌های عمومی (SPA‌ها، برنامه‌های موبایل) که نمی‌توانند client secret را به صورت امن ذخیره کنند الزامی است.