🎫
JWT — rol ko'tarish
Token roliga ishonish
1
Maqsad
token ichidagi rolni ishonch bilan o'zgartirishJWT o'zgartirilmaydi — imzo bor. Lekin server ko'p hollarda
token ichidagi role maydonini to'g'ridan-to'g'ri
ishonch bilan ishlatadi, bazasidan qayta tekshirmaydi. Bu — eng
ko'p uchraydigan JWT zaifligi.
2
Tushuntirish
// XAVFLI const decoded = jwt.verify(token, SECRET); // imzo tekshirildi — OK if (decoded.role === 'admin') return adminPanel(); // ↑ imzo to'g'ri, LEKIN eski token hali ham "admin" deydi // TO'G'RI — rolda DB dan const decoded = jwt.verify(token, SECRET, {{ algorithms:['HS256'] }}); const user = await prisma.user.findUnique({{ where: {{ id: decoded.sub }} }}); if (user.role === 'admin' && user.isActive) return adminPanel(); if (user.role !== decoded.role) await revokeAll(user.id); // rol o'zgargan
Ikkita alohida holat
1) Ishonch bilan ishlatish — token'dagi rolda qaror beriladi. 2) Eski token — foydalanuvchi adminlikdan tushdirilgan, lekin eski tokeni 1 soat amal qiladi.
3
Qanday aniqlanadi
# 1) roldan foydalanish joylari grep -rnE "req\.user\.(role|isAdmin)|decoded\.(role|is_admin)|payload\.role" src/ # 2) rolda DB dan olinadimi? grep -rnE "findUnique.*user|prisma\.user\.|User\.findOne" src/ | head # 3) token muddati grep -rnE "expiresIn|exp:|maxAge" src/ | head
4
Buyruqlar
# 1) oddiy user tokenini oling TOKEN=$(curl -s -X POST https://site.uz/api/auth/login \ -H "Content-Type: application/json" \ -d '{"email":"oddiy@site.uz","password":"..."}' | jq -r .token) echo "$TOKEN" | cut -d. -f2 | base64 -d 2>/dev/null; echo # 2) rolda o'zgartirib, imzoni saqlab qolamiz (kalitni bilmaymiz) # → bu imzoni buzadi. Shuning uchun 3-usul qo'llaniladi: # 3) asosiy test: rolda serverga qarab o'zgaradimi? curl -s https://site.uz/api/admin/users -H "Authorization: Bearer $TOKEN" | jq . curl -s https://site.uz/api/me -H "Authorization: Bearer $TOKEN" | jq '.role' # token'da "user", lekin /api/admin/users 200 qaytarib bo'lsa — zaiflik # 4) turli ro'l nomlari bilan for R in admin administrator superadmin super_user root 1 true; do echo "$R → $(curl -s -o /dev/null -w '%{http_code}' https://site.uz/api/admin \ -H "Authorization: Bearer $TOKEN")" done # 5) status/flag maydonlari curl -s https://site.uz/api/me -H "Authorization: Bearer $TOKEN" | jq 'del(.token,.passwordHash)' # 6) eski token muammusini tekshirish (o'z saytingizda) # a) admin tokenni yarating va 1 soat saqlang (test maqsadida) # b) foydalanuvchini adminlikdan chiqaring # c) eski token bilan /api/admin ni so'rang curl -s -o /dev/null -w "eskirgan token → HTTP %{http_code}\n" \ https://site.uz/api/admin -H "Authorization: Bearer $ESKI_TOKEN" # 200 → muammo bor (token bekor qilinmagan) # 7) jwks / kid tekshiruvi curl -s https://site.uz/api/auth/me -H "Authorization: Bearer $TOKEN" | jq '{kid, sub, role, iat, exp}'
5
Natija
✓ MUvaffaqiyat — hujum ISHLADI
| Server javobi | Nima degani |
|---|---|
`/api/admin` 200 qaytardi | **Rol token'dan olinadi — zaiflik** |
`role: "user"` lekin admin panel ochildi | **Ishonch bilan qaror** |
Tushirilgan foydalanuvchi eski token bilan kirdi | **Token bekor qilinmagan** |
`isActive: false` lekin kirish qoldi | **Holat tekshirilmaydi** |
✗ Rad etish — hujum ISHLAMADI
| Server javobi | Nima degani |
|---|---|
`/api/admin` → 403 | **To'g'ri** — rol DB dan tekshiriladi |
`role` token'da o'zgarib, javob o'zgarmadi | **Ishonchli rol** |
Tushirilgandan keyin 401 | **Token bekor qilindi** — to'g'ri |
6
Zararni yopish
1. Rolni DB dan olish (qat'iy)
function auth(req, res, next) {{
const d = jwt.verify(req.headers.authorization.slice(7), SECRET, {{
algorithms: ['HS256']
}});
req.token = d; // faqat kimligi (sub)
next();
}}
async function loadUser(req, res, next) {{
req.user = await prisma.user.findUnique({{ where: {{ id: Number(req.token.sub) }} }});
if (!req.user || !req.user.isActive) return res.status(401).end();
if (req.user.role !== req.token.role) req.tokenStale = true; // ogohlantirish
next();
}}
app.use('/api', auth, loadUser);
// keyin HAR QAYERDA
if (req.user.role === 'admin') ... // ← token emas, DB
2. Token bekor qilish
# parol o'zgarganda / logout da — token qora ro'yxati await redis.set(`revoked:${{d.jti}}`, 1, {{ EX: 3600 }}); if (await redis.get(`revoked:${{d.jid}}`)) return fail(); # yoki versiya usuli (eng oddiy) # user.tokenVersion raqamini oshirish; token'da versiyani solishtirish if (d.ver !== req.user.tokenVersion) return fail();
3. Token muddatini qisqartirish
jwt.sign(payload, SECRET, {{ algorithm:'HS256', expiresIn:'15m' }});
// + refresh token (15 daqiqa / 7 kun, faqat /refresh da)
7
Tekshirish ro'yxati
- Rol `req.user` dan (DB) olinadi, token'dan emas
- `algorithms: ['HS256']` ko'rsatilgan
- `isActive` va `emailVerified` tekshiriladi
- Parol o'zgarganda eski tokenlar bekor qilinadi
- Access token 15 daqiqa
- Oddiy user token bilan `/api/admin` so'raldi