JWT چطور کار میکند؟
پس از ورود موفق، سرور یک توکن امضاشده میسازد و به کلاینت میدهد. کلاینت آن را در هدر Authorization: Bearer … هر درخواست میفرستد و سرور فقط با بررسی امضا، هویت را میشناسد، بدون اینکه به پایگاهداده یا حافظهی نشست سر بزند. این بدونحالتبودن، JWT را برای APIهای مقیاسپذیر جذاب میکند.
یک JWT سه بخش جداشده با نقطه دارد: هدر (الگوریتم)، بدنه (claimها) و امضا. بخشهای اول و دوم فقط Base64URL هستند و هر کسی میتواند بخواندشان؛ امضا فقط جلوی دستکاری را میگیرد.
// payload of a typical access token
{
"sub": "user_42", // who
"iss": "https://api.example.com",
"aud": "example-web",
"iat": 1795000000,
"exp": 1795000900, // 15 minutes later
"role": "editor"
}Access token و refresh token
اگر توکن دزدیده شود، تا زمان انقضا معتبر است و سرور بدونحالت نمیتواند آن را «لغو» کند. بنابراین از دو توکن استفاده میکنیم:
| ویژگی | Access token | Refresh token |
|---|---|---|
| عمر | ۵ تا ۱۵ دقیقه | چند روز تا چند هفته |
| کاربرد | فراخوانی APIها | فقط دریافت access token جدید |
| ذخیره در سرور | ندارد | هش آن در پایگاهداده ذخیره میشود |
| ابطال | با انقضای کوتاه | حذف رکورد از پایگاهداده |
بهتر است refresh token چرخشی (rotating) باشد: با هر استفاده، توکن جدید صادر و قبلی باطل میشود. اگر توکن قدیمی دوباره ظاهر شد، یعنی کسی آن را کپی کرده؛ کل خانوادهی توکنهای آن نشست را باطل کنید. چون ابطال، رکورد سمت سرور میخواهد، میتوانید فهرستهای سریع را در Redis نگه دارید.

صدور و اعتبارسنجی درست
نمونهای با کتابخانهی jsonwebtoken در Node.js. نکتهی کلیدی در اعتبارسنجی، تعیین صریح الگوریتم و issuer/audience است:
const jwt = require("jsonwebtoken");
function issue(user) {
return jwt.sign({ sub: user.id, role: user.role }, process.env.JWT_SECRET, {
algorithm: "HS256", expiresIn: "15m",
issuer: "https://api.example.com", audience: "example-web"
});
}
function verify(token) {
// throws on bad signature, expiry, wrong iss/aud or other algorithm
return jwt.verify(token, process.env.JWT_SECRET, {
algorithms: ["HS256"],
issuer: "https://api.example.com", audience: "example-web"
});
}- کلید را در متغیر محیطی نگه دارید و حداقل ۳۲ بایت تصادفی باشد؛ هرگز در مخزن کد نگذارید.
- اگر چند سرویس توکن را بررسی میکنند، بهجای کلید مشترک از امضای نامتقارن (
RS256یاES256) استفاده کنید تا فقط یک سرویس بتواند توکن بسازد. - رمزها را با
argon2یاbcryptهش کنید، نه SHA ساده.
توکن را کجا نگه داریم؟
در مرورگر دو گزینهی اصلی دارید و هر دو معاوضه دارند:
- localStorage: پیادهسازی ساده، اما هر اسکریپتی که روی صفحه اجرا شود (مثلاً با یک حفرهی XSS یا وابستگی آلوده) میتواند توکن را بخواند.
- کوکی HttpOnly + Secure + SameSite: جاوااسکریپت به آن دسترسی ندارد، پس سرقت با XSS دشوارتر است؛ در عوض باید در برابر CSRF با
SameSite=LaxیاStrictو توکن CSRF محافظت کنید.
res.cookie("refresh_token", token, {
httpOnly: true, secure: true, sameSite: "strict",
path: "/auth/refresh", maxAge: 7 * 24 * 3600 * 1000
});الگوی عملی: access token را در حافظهی برنامه نگه دارید و refresh token را در کوکی HttpOnly که فقط به مسیر /auth/refresh ارسال میشود. در موبایل از Keychain یا Keystore استفاده کنید.
خطاهای رایج که امنیت را از بین میبرند
- پذیرفتن
alg: noneیا الگوریتم دلخواه توکن. الگوریتم را سمت سرور ثابت کنید و از پارامترalgorithmsاستفاده کنید. - رمز ضعیف برای HS256. کلیدهای کوتاه با حملهی brute-force شکسته میشوند.
- عمر طولانی access token. «۳۰ روز» یعنی یک ماه فرصت برای مهاجم.
- نادیدهگرفتن
expوaud. توکن یک سرویس نباید در سرویس دیگر پذیرفته شود. - اعتماد به claim نقش بدون بررسی. برای عملیات حساس، دسترسی را از پایگاهداده هم تأیید کنید.
- لاگکردن توکن کامل. توکن در لاگ یعنی لو رفتن آن به هرکس که لاگ را میبیند.
فهرست جامعتر خطرهای API را در OWASP API Security Project ببینید و جزئیات استاندارد را در راهنمای احراز هویت HTTP در MDN بخوانید.
آیا اصلاً به JWT نیاز دارید؟
برای یک سایت یکپارچهی ساده که فقط یک سرور دارد، نشست سمت سرور با کوکی (session) سادهتر و امنتر است و ابطالش لحظهای است. JWT زمانی میارزد که چند سرویس مستقل یا اپلیکیشن موبایل و وب با یک API کار کنند و نخواهید هر درخواست به مخزن نشست مشترک برسد.
اگر معماری شما به سمت سرویسهای جدا میرود، مقالهی معماری میکروسرویسها نشان میدهد توکنها در این مرزها چه نقشی دارند. هر احراز هویتی هم باید با تست پوشش داده شود؛ نمونهی آن در تست خودکار در لاراول آمده است. و اگر سامانهی ورود یا API امن برای محصولتان میخواهید، با ما تماس بگیرید.
پرسشهای متداول
JWT امن است؟
خود فرمت امن است، به شرط پیادهسازی درست: الگوریتم ثابت، کلید قوی، عمر کوتاه، اعتبارسنجی exp و aud و ذخیرهسازی محتاطانه. بیشتر حفرهها از پیادهسازی میآیند نه از استاندارد.
JWT را کجا ذخیره کنم؟
برای وب، کوکی HttpOnly با Secure و SameSite معمولاً بهتر از localStorage است، چون جاوااسکریپت صفحه نمیتواند آن را بخواند. در موبایل از Keychain در iOS و Keystore در اندروید استفاده کنید.
چطور JWT را باطل کنم؟
access token کوتاهعمر را به انقضا بسپارید و refresh token را در پایگاهداده نگه دارید تا با حذف رکورد باطل شود. برای ابطال فوری میتوانید شناسهی توکن (jti) را در فهرست سیاه Redis بگذارید.
تفاوت JWT و session چیست؟
در session دادهی نشست سمت سرور است و کلاینت فقط شناسه دارد؛ در JWT اطلاعات داخل توکن امضاشده است. session ابطال سادهتری دارد و JWT بدونحالتتر است.

دیدگاهها
هنوز دیدگاهی ثبت نشده است. اولین نفر باشید.