JWT (JSON Web Token) — قالبی فشرده برای انتقال داده بین طرفها به صورت یک شیء JSON است که با امضای دیجیتال محافظت میشود. توکن میتواند با HMAC (کلید متقارن) یا RSA/ECDSA (جفت نامتقارن) امضا شود که یکپارچگی و اصالت داده را تضمین میکند. بر اساس IETF RFC 7519، 2015، JWT در میلیونها برنامه برای احراز هویت، تبادل امن claims و به عنوان فرمت ID Token در OpenID Connect استفاده میشود.
نکات اصلی
JSON Web Token (JWT) — استانداردی باز (RFC 7519) است که روشی فشرده و خودکفا برای انتقال اطلاعات بین طرفها به صورت یک شیء JSON تعریف میکند. اطلاعات در JWT claims نامیده میشوند — ادعاهایی درباره موضوع (کاربر) و ویژگیهای اضافی. هر claim یک جفت کلید-مقدار است: شناسه کاربر، نقش، زمان انقضا، صادرکننده.
JWT خودکفا نامیده میشود زیرا تمام اطلاعات لازم برای تأیید در داخل خود توکن قرار دارد. سرور برای اطمینان از اعتبار توکن نیازی به مراجعه به پایگاه داده یا ذخیرهسازی خارجی ندارد — فقط کافی است امضا را بررسی کند. این ویژگی JWT را برای سیستمهای توزیعشده و معماری میکروسرویس ایدهآل میکند، جایی که چندین سرویس باید درخواستها را بدون ذخیرهسازی مشترک جلسات احراز هویت کنند.
بر اساس دادههای Auth0، 2025، بیش از 65% از برنامههای موبایل و وب از JWT به عنوان فرمت اصلی توکن برای احراز هویت API استفاده میکنند، پیشی گرفتن از توکنهای opaque و شناسههای جلسه.
JWT از سه بخش تشکیل شده که با نقطه از هم جدا شدهاند: header.payload.signature. هر بخش یک JSON کدگذاری شده با Base64url است. بیایید هر بخش را به تفصیل بررسی کنیم.
Header شامل دو فیلد اجباری است: alg (algorithm — الگوریتم امضا) و typ (type — نوع توکن، همیشه «JWT»). الگوریتم میتواند متقارن (HS256 — HMAC با SHA-256) یا نامتقارن (RS256 — RSA با SHA-256، ES256 — ECDSA با P-256) باشد. الگوریتمهای نامتقارن ترجیح داده میشوند زیرا به کلاینت اجازه میدهند بدون داشتن کلید مخفی امضا را بررسی کند.
مثال header کدگشایی شده:
{
"alg": "RS256",
"typ": "JWT",
"kid": "key-id-1"
}
Payload شامل claims — ادعاهایی درباره موضوع است. Claims به سه نوع تقسیم میشوند: ثبتشده (iss، sub، aud، exp، nbf، iat، jti)، عمومی (تعریف شده توسط توسعهدهنده در IANA Registry) و خصوصی (توافق شده بین طرفها). sub (subject) — شناسه یکتای کاربر. exp (expiration) — زمان انقضای توکن. iss (issuer) — صادرکننده توکن.
{
"sub": "user-abc-123",
"iss": "https://auth.example.com",
"aud": "my-mobile-app",
"exp": 1812345678,
"iat": 1812342078,
"role": "premium_user"
}
Signature با اعمال الگوریتم امضا بر روی الحاق header و payload با استفاده از کلید مخفی یا خصوصی ایجاد میشود. فرمول: HMACSHA256(base64UrlEncode(header) + «.» + base64UrlEncode(payload), secret) برای HMAC، یا RSASHA256(...) برای الگوریتم نامتقارن. دریافتکننده امضا را به همان روش محاسبه کرده و با دریافتشده مقایسه میکند — اگر مطابقت داشتند، دادهها تغییر نکردهاند.
فرآیند کار با JWT از دو فاز تشکیل شده است: ایجاد (صدور) توکن توسط سرور احراز هویت و بررسی توکن توسط کلاینت یا سرور منابع. سرور احراز هویت اطلاعات کاربر را دریافت میکند، payload با claims ایجاد کرده و آن را امضا میکند. JWT حاصل در پاسخ به درخواست ورود یا در بدنه پاسخ OAuth 2.0 / OpenID Connect به کلاینت ارسال میشود.
در برنامههای موبایل JWT به صورت زیر استفاده میشود: پس از ورود موفق، کاربر یک access token در قالب JWT دریافت میکند. برنامه آن را در ذخیرهسازی امن ذخیره میکند (Keychain در iOS، EncryptedSharedPreferences در Android). در هر درخواست به API، برنامه هدر Authorization: Bearer <token> را اضافه میکند. سرور API امضای JWT را بررسی میکند، claims را استخراج کرده و بر اساس آنها تصمیم دسترسی میگیرد — بدون مراجعه به پایگاه داده.
بر اساس دادههای Google Codelabs، 2025، استفاده از JWT در Firebase Authentication تعداد درخواستها به سرور احراز هویت را 40–60% در مقایسه با توکنهای جلسه کاهش میدهد، زیرا دادهها به صورت محلی روی هر میکروسرویس بررسی میشوند. این به ویژه برای معماریهای با بار بالا مهم است، جایی که هر میلیثانیه تأخیر بر تجربه کاربر تأثیر میگذارد. با 50 000 درخواست در دقیقه، انتقال به JWT میتواند تا 10 نمونه سرور پردازشکننده درخواستهای introspection را ذخیره کند.
JWT و Session Token یک مسئله را حل میکنند — احراز هویت درخواستها — اما از نظر معماری اساساً متفاوت هستند. Session Token یک رشته شناسه تصادفی است که به دادههای جلسه ذخیره شده در سرور اشاره میکند (stateful). JWT — توکن خودکفا حاوی تمام دادهها در خود (stateless).
| پارامتر | JWT | Session Token |
|---|---|---|
| ذخیره داده | داخل توکن (خودکفا) | روی سرور (ذخیرهسازی جلسه) |
| مقیاسپذیری | نیاز به ذخیره مشترک ندارد | برای چند سرور نیاز به Redis/DB دارد |
| لغو توکن | مشکل (لیست سیاه نیاز است) | ساده (حذف جلسه از DB) |
| اندازه | بزرگ (500–2000 بایت) | کوچک (16–64 بایت) |
| بررسی امضا | رمزنگاری | ندارد (مقایسه رشتهها) |
JWT در سیستمهای توزیعشده برتری دارد: میکروسرویسها میتوانند توکن را به صورت محلی بدون ذخیره مشترک بررسی کنند. به عنوان مثال، در معماری با پنج میکروسرویس، هر سرویس JWT را در 1–2 میلیثانیه بدون فراخوانی شبکه بررسی میکند، در حالی که session token در هر درخواست نیاز به مراجعه به Redis متمرکز دارد و 10–30 میلیثانیه تأخیر اضافه میکند. با این حال، لغو JWT دشوار است — اگر توکن صادر شده باشد، تا زمان انقضا معتبر است. Session Token به راحتی با حذف رکورد از DB یا Redis لغو میشود.
برای برنامههای موبایل، رویکرد ترکیبی — JWT با عمر کوتاه (15–30 دقیقه) و Refresh Token — تعادل بین عملکرد و امنیت ایجاد میکند. JWT برای دسترسی به API استفاده میشود و refresh token (معمولاً opaque) برای دریافت JWTهای جدید. در صورت به خطر افتادن JWT، مهاجم به مدت 15–30 دقیقه دسترسی دارد; در صورت به خطر افتادن refresh token، جلسه از طریق چرخش و تشخیص استفاده مجدد مسدود میشود.
امنیت JWT به پیادهسازی صحیح بستگی دارد. رایجترین آسیبپذیری حمله «alg none» است: مهاجم header توکن را به «alg»: «none» تغییر میدهد و سرور بدون بررسی الگوریتم، توکن جعلی را میپذیرد. محافظت: همیشه بررسی کنید که الگوریتم در header با الگوریتم مورد انتظار (RS256، ES256) مطابقت دارد و توکنهای با alg: none را رد کنید.
آسیبپذیریهای JWT همچنین شامل موارد زیر است: کلید مخفی ضعیف برای HMAC (شکستن در عرض چند دقیقه)، نشت کلید خصوصی (امضای هر داده به نام سرور)، ذخیره دادههای حساس در payload (JWT رمزگذاری نمیکند، فقط امضا میکند)، حمله از طریق تزریق هدر JWK (وارد کردن کلید عمومی خود). استفاده از کتابخانههای معتبر — Nimbus JOSE + JWT، jjwt (io.jsonwebtoken)، PyJWT — خطر بهرهبرداری از این آسیبپذیریها را کاهش میدهد.
یک اقدام حفاظتی اضافی — JWK Thumbprint (RFC 7638): اتصال کلید عمومی به توکن از طریق اثر انگشت (thumbprint) در header. اگر سرور thumbprint مورد انتظار را برای هر کلاینت ذخیره کند، حمله تزریق هدر JWK غیرممکن میشود — سرور هر کلیدی را که با کلید ثبتشده مطابقت نداشته باشد رد میکند. OAuth Security Workshop 2025، JWK Thumbprint را به عنوان حفاظت اجباری برای همه JWTهای استفادهشده در برنامههای مالی و پزشکی توصیه میکند.
کتابخانه jjwt (auth0/java-jwt) امکان ایجاد و بررسی JWT را در برنامه Android در چند خط فراهم میکند. در مثال زیر، سرور توکنی با sub و role تولید میکند و کلاینت امضا را بررسی میکند. برای ذخیره امن کلید مخفی در سرور از متغیرهای محیطی یا HSM (Hardware Security Module) استفاده کنید — ذخیره کلید در کد یا فایل پیکربندی یک اشتباه امنیتی فاحش است.
val secret = "my-256-bit-secret-key-here"
val token = JWT.create()
.withSubject("user-abc-123")
.withIssuer("auth.example.com")
.withClaim("role", "premium_user")
.withExpiresAt(Date(System.currentTimeMillis() + 3600000))
.sign(Algorithm.HMAC256(secret))
// ارسال توکن به کلاینت
println("JWT: $token")
fun verifyToken(token: String): Boolean {
return try {
val decoded = JWT.require(Algorithm.HMAC256(secret))
.withIssuer("auth.example.com")
.build()
.verify(token)
// امضا صحیح است، claims استخراج شد
println("Subject: ${decoded.subject}")
true
} catch (e: Exception) {
println("Token invalid: ${e.message}")
false
}
}
سوالات متداول
خیر. JWT امضا میشود نه رمزگذاری — هر کسی میتواند payload Base64 را کدگشایی کرده و دادهها را بخواند. اطلاعات حساس (رمز عبور، شماره کارت، دادههای شخصی) باید فقط به صورت رمزگذاریشده از طریق JWE (JSON Web Encryption) منتقل شوند.
ES256 (ECDSA با P-256) توصیه میشود — سطح امنیت معادل RSA 2048-bit را با اندازه امضای بسیار کوچکتر فراهم میکند. برای سازگاری با سیستمهای قدیمی، RS256 مناسب است. HS256 (HMAC) نیاز به تبادل امن کلید مخفی دارد که در معماری توزیعشده دشوارتر است.
JWT را نمیتوان مستقیماً لغو کرد — تا exp معتبر است. راهحلها: استفاده از عمر کوتاه (15–30 دقیقه)، نگهداری لیست سیاه jtiهای لغوشده (JWT ID) در سرور، یا اتصال توکنها به نسخه کلید مخفی. Refresh token به صورت استاندارد — با حذف از ذخیرهسازی — لغو میشود.
Bearer token — یک مفهوم است: هر توکنی که دارنده (bearer) میتواند برای دسترسی استفاده کند. JWT — یک فرمت خاص از توکن است. Bearer token میتواند JWT باشد یا یک رشته opaque. JWT به مفهوم Bearer خودکفایی و تأیید رمزنگاری اضافه میکند.
یک JWT معمولی با امضای RS256 500–2000 بایت است. اگر payload حاوی claims سفارشی زیادی باشد یا از امضای نامتقارن با کلید بزرگ استفاده شود، اندازه میتواند به 4–5 KB برسد. این به طور قابل توجهی بیشتر از session token (16–64 بایت) است که بر اندازه هدرهای HTTP تأثیر میگذارد.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید