JWT (JSON Web Token) چیست؟
JSON Web Token (JWT) یک قالب توکن فشرده و URL-safe است که در RFC 7519 تعریف شده است. این قالب مجموعهای از کلیمها را به صورت یک شیء JSON کدگذاری میکند، سپس آن را امضا — و در صورت نیاز رمزنگاری — میکند تا گیرنده بتواند تأیید کند که دادهها دستکاری نشدهاند. JWT استاندارد de facto برای احراز هویت بدون حالت در REST API ها، سیستمهای ورود یکپارچه و مجوزدهی در میکروسرویسهاست.
RFC 7519 — JSON Web Token (JWT) →
ساختار JWT: Header · Payload · Signature
هر JWT از سه بخش base64url-encoded جدا شده با نقطه تشکیل شده است. هدر و پیلود JSON ساده هستند — قابل خواندن توسط هر کسی — در حالی که امضا یک مقدار رمزنگاریشده است که تنها با کلید صحیح قابل تأیید است.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyMTIzIiwibmFtZSI6IkFsaWNlIiwicm9sZSI6ImFkbWluIiwiaWF0IjoxNzE3MjAwMDAwLCJleHAiOjE3MTcyMDM2MDB9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
{
"alg": "HS256",
"typ": "JWT"
}{
"sub": "user123",
"name": "Alice",
"role": "admin",
"iat": 1717200000,
"exp": 1717203600
}چرا از رمزگشای JWT استفاده کنیم؟
JWT های خام شبیه متن تصادفی به نظر میرسند. این ابزار فوری هدر و پیلود را به صورت JSON فرمتشده نمایش میدهد تا بتوانید کلیمها را بررسی کنید، زمان انقضا را چک کنید و انتخابهای الگوریتمی را بدون نوشتن حتی یک خط کد بررسی کنید.
مرجع کلیمهای استاندارد JWT
RFC 7519 هفت نام کلیم ثبتشده تعریف میکند. اینها الزامی نیستند، اما استفاده از آنها برای قابلیت تعاملپذیری به شدت توصیه میشود. میتوانید هر کلیم سفارشی دیگری را به پیلود اضافه کنید.
| کلیم | توضیح | نوع |
|---|---|---|
| iss | Issuer — مشخص میکند چه کسی توکن را صادر کرده — مثلاً URL سرور احراز هویت یا نام برنامه شما. | string |
| sub | Subject — موضوع اصلی JWT را مشخص میکند — معمولاً شناسه کاربر یا حساب سرویس. | string |
| aud | Audience — گیرندگان مورد نظر را مشخص میکند. طرف دریافتکننده باید تأیید کند که این با شناسه خودش مطابقت دارد. | string | string[] |
| exp | Expiration Time — تایماستمپ Unix که پس از آن توکن نباید پذیرفته شود. همیشه این را تنظیم کنید تا خسارت از یک توکن دزدیدهشده محدود شود. | number |
| nbf | Not Before — تایماستمپ Unix که قبل از آن توکن نباید پذیرفته شود. برای برنامهریزی توکنهای با تاریخ آینده مفید است. | number |
| iat | Issued At — تایماستمپ Unix که در آن توکن صادر شده. برای محاسبه عمر توکن استفاده میشود. | number |
| jti | JWT ID — یک شناسه منحصربهفرد برای توکن. امکان ابطال را با ذخیره و بررسی مقادیر JTI استفادهشده در سمت سرور فراهم میکند. | string |
الگوریتمهای امضای JWT
کلیم هدر alg اعلام میکند کدام الگوریتم توکن را امضا کرده است. این انتخاب روی امنیت، کارایی و اینکه آیا سرویسهای شخص ثالث میتوانند توکنها را بدون کلید خصوصی تأیید کنند تأثیر میگذارد.
| الگوریتم | خانواده | نوع کلید | یادداشتها |
|---|---|---|---|
| HS256 | HMAC | Symmetric | رایجترین. کلید مخفی مشترک — هر کسی با کلید مخفی میتواند هم امضا کند و هم تأیید کند. |
| HS384 | HMAC | Symmetric | نوع قویتر HMAC؛ هزینه کارایی متوسط. |
| HS512 | HMAC | Symmetric | قویترین نوع HMAC. |
| RS256 | RSA | Asymmetric | پرکاربردترین الگوریتم نامتقارن (Google، Auth0، Okta). کلید عمومی بدون کلید خصوصی تأیید میکند. |
| RS384 | RSA | Asymmetric | نوع RS با امنیت بالاتر. |
| RS512 | RSA | Asymmetric | قویترین نوع RS. |
| ES256 | ECDSA | Asymmetric | منحنی بیضوی — امضاهای کوتاهتر از RSA، محبوب در موبایل و IoT. |
| PS256 | RSA-PSS | Asymmetric | RSA-PSS: مدرنتر و امنتر از RS256 مبتنی بر PKCS1v1.5. |
| none | — | — | بدون امضا — بسیار خطرناک. هرگز در محیط تولید توکنهایی با alg: none را نپذیرید. |
ملاحظات امنیتی
رمزگشایی یک JWT همیشه امن است. اعتماد به JWT بدون تأیید صحیح امضا امن نیست.
- –رمزگشایی و بررسی یک JWT در ابزارهای توسعهدهنده یا این ابزار
- –استفاده از exp، iat و nbf برای درک طول عمر توکن
- –ثبت کلیمهای پیلود برای اشکالزدایی (اطلاعات شخصی حساس را حذف کنید)
- –خواندن هدر alg برای درک نحوه امضای توکن
- –اعتماد به کلیمهای پیلود بدون تأیید امضا در سمت سرور
- –پذیرفتن توکنهایی با alg: none — این به معنای عدم وجود هیچ امضایی است
- –ذخیره توکنهای دسترسی در localStorage در برنامههای با امنیت بالا (کوکیهای httpOnly را ترجیح دهید)
- –تنظیم exp در آیندهای دور برای توکنهایی که مجوزهای حساس دارند
موارد استفاده رایج
رمزگشایی JWT در کد
هدر و پیلود base64url-encoded هستند — فقط رمزگذاری را معکوس کنید. Base64url به جای + از - و به جای / از _ استفاده میکند و = padding را حذف میکند. تنها امضا به کلید مخفی نیاز دارد.
function decodeJWT(token) {
const [, payload] = token.split('.')
const json = atob(payload.replace(/-/g, '+').replace(/_/g, '/'))
return JSON.parse(json)
}const [, payload] = token.split('.')
const decoded = JSON.parse(
Buffer.from(payload, 'base64url').toString()
)import base64, json
def decode_jwt(token):
payload = token.split('.')[1]
padding = '=' * (-len(payload) % 4)
return json.loads(base64.urlsafe_b64decode(payload + padding))TOKEN="eyJhbGc..." echo $TOKEN | cut -d. -f2 | base64 -d 2>/dev/null | jq .