WisarWisar
Dasturlash kitobi/14-QISM — Xavfsizlik37 daqiqa

14.5-bob: Autentifikatsiya va parol xavfsizligi

14-QISM — Web Xavfsizligi · 5-mavzu


1. Kirish va motivatsiya

Autentifikatsiya (foydalanuvchini tanish — kim? — 13.9: 2.1) — har ilovaning eshigi. Va eshik qulfini noto'g'ri qo'ysangiz — barcha ichkaridagi narsa xavfda. OWASP A07 (Authentication Failures) — eng keng zaifliklardan: zaif parol siyosati, parolni ochiq saqlash, brute force (parolni minglab marta sinash), sessiya o'g'irlik. Eng katta ma'lumot sizishlari ko'pincha autentifikatsiya xatosidan boshlanadi (zaif parol hisob egallash butun tizimga kirish). Bu bobda autentifikatsiyani xavfsiz qilishni — eng muhim qismidan (parol saqlash) boshlab — to'liq ko'ramiz.

Eng asosiy va eng ko'p buzuladigan qoida: parol hech qachon ochiq saqlanmaslik kerak. Parol DB'da hash (bir tomonlama, qaytarib bo'lmaydigan) holda saqlanadi — agar DB sizsa (o'g'irlansa), hujumchi hash'larni ko'radi, lekin haqiqiy parolni ola olmaydi (hash'dan parolni teskari ocha bo'lmaydi). Lekin hash ham to'g'ri qilinishi kerak (oddiy hash — MD5, SHA — yetarli emas — bcrypt/argon2 kerak). Bundan tashqari — kuchli parol talabi, brute force himoyasi (rate limit), ikki bosqichli (2FA), sessiya xavfsizligi. Bu bob bularning hammasini (nega va qanday) ochadi.

Bu bob: parol xeshlash (nega ochiq emas, bcrypt/argon2 — qanday), salt va hash funksiyalari (nega MD5/SHA xato), parol siyosati (kuchli parol, NIST tavsiyalari), brute force himoyasi (rate limit, lockout, CAPTCHA), 2FA/MFA (ikki bosqichli), sessiya xavfsizligi, va keng auth xatolari. Autentifikatsiya xavfsizligi va parol xeshlash — to'liq va tartib bilan ko'rib chiqiladi.

O'xshatish: Parol xeshlash — bu bir tomonlama yo'lakda go'sht qiymasi. Parolni qiymalash mashinasiga (hash funksiyasi) solsangiz — qiyma (hash) chiqadi. Lekin qiymadan qaytadan butun go'sht (asl parol) yasab bo'lmaydi (bir tomonlama). DB sizsa, hujumchi qiymani (hash) ko'radi, lekin asl go'shtni (parol) tiklay olmaydi. Salt — bu har qiymaga qo'shilgan noyob ziravor: ikki bir xil parol ham, har xil salt bilan, har xil hash beradi (oldindan tayyorlangan "qiyma katalogi" — rainbow table — ishlamaydi). bcrypt/argon2 — sekin, kuchli qiymalash mashinasi (atayin sekin — hujumchi minglab parolni sinash uchun har birini sekin qiymalashga majbur — brute force qiyinlashadi). MD5/SHA — tez mashina (yomon — hujumchi sekundda millionlab sinaydi). To'g'ri parol saqlash — sekin, salt bilan, bir tomonlama.

Nega muhim?

  • A07 (OWASP) — autentifikatsiya xatosi eng keng hisob egallash sababi.
  • Parol ochiq = falokat — DB sizsa barcha parol ochiq (odamlar bir parolni ko'p saytda ishlatadi).
  • Brute force — zaif parol + himoyasiz = soatlarda buziladi.
  • Har ilova poydevori — autentifikatsiya har ilovada (xato = hamma narsa xavfda).

2. Nazariya — chuqur tushuntirish

2.1. Nega parol ochiq saqlanmaydi

text
  PAROL OCHIQ SAQLASH — eng katta xato (DB sizsa — falokat):

   OCHIQ (plaintext):
  users: { email: "ali@x.com", password: "mening_parolim123" }
   DB sizsa (SQL injection, ichki xodim, backup o'g'irlik) — BARCHA parol ochiq!

  NEGA HALOKATLI:
   odamlar bir parolni KO'P saytda ishlatadi (email, bank, ijtimoiy)
   bitta saytdan sizgan parol — boshqa saytlarga ham kirish (credential stuffing)

   HASH (bir tomonlama):
  users: { email: "ali@x.com", passwordHash: "$2b$10$N9qo8uLOick..." }
   DB sizsa — hujumchi HASH'ni ko'radi, ASL parolni OLA OLMAYDI
   hash'dan parolni teskari ocha bo'lmaydi (bir tomonlama matematika)

   Parol HECH QACHON ochiq saqlanmaydi — HASH (bir tomonlama — DB sizsa ham himoyalangan)
   Odamlar parolni qayta ishlatadi  bir sizish = ko'p hisob (credential stuffing)

Nega parol ochiq saqlanmaydi — autentifikatsiya xavfsizligining eng asosiy qoidasi. Ochiq saqlash (plaintext): password: "mening_parolim123" — parolni DB'da o'qiladigan holda saqlash. Nega halokatli: agar DB sizsa (SQL injection — 14.3, ichki xodim, backup o'g'irlik, server buzilishi) — barcha foydalanuvchi paroli ochiq hujumchi qo'lida. Bu juda jiddiy chunki: (1) odamlar bir parolni ko'p saytda ishlatadi (email, bank, ijtimoiy tarmoq — bir xil parol); (2) bitta saytdan sizgan parol bilan hujumchi boshqa saytlarga ham kiradi (credential stuffing — sizgan email/parolni boshqa saytlarda sinash — ko'pincha ishlaydi). Ya'ni sizning kichik saytingizdan parol sizsa — foydalanuvchining bank hisobi ham xavfda. Hash (bir tomonlama): passwordHash: "$2b$10$N9qo8uLOick..." — parolni hash (matematik bir tomonlama funksiya) bilan saqlash — agar DB sizsa, hujumchi hash'ni ko'radi, lekin asl parolni ola olmaydi (hash'dan parolni teskari ocha bo'lmaydi — bu hash funksiyasining asosiy xususiyati — bir tomonlama). Ikki nuqta: (1) parol hech qachon ochiq saqlanmaydi — hash (bir tomonlama — DB sizsa ham parollar himoyalangan); (2) odamlar parolni qayta ishlatadi bir sizish = ko'p hisob (credential stuffing — sizning mas'uliyatingiz boshqa saytlarga ham ta'sir qiladi). Bu — eng asosiy va eng ko'p buzuladigan qoida (ko'p kichik loyiha parolni ochiq saqlaydi — "hech kim buzmaydi" deb — falokat). Parol hash — autentifikatsiyaning birinchi va eng muhim qoidasi.

2.2. Hash funksiyalari (nega bcrypt/argon2)

text
  HASH FUNKSIYASI — to'g'ri tanlash (oddiy hash YETARLI EMAS):

   MD5, SHA-256 (umumiy hash — parol uchun XAVFLI):
   CHAQQON (tez) — hujumchi sekundda MILLIONLAB parolni sinaydi (brute force)
   rainbow table (oldindan hisoblangan hash katalogi) — tez topadi

   bcrypt, argon2, scrypt (parol uchun MAXSUS — sekin):
   ATAYIN SEKIN (har hash millisekund — hujumchi sekundda kam sinaydi)
   "cost factor" (sozlanadigan sekinlik — kompyuter tezlashsa oshiriladi)
   salt avtomatik (rainbow table ishlamaydi — 2.3)

  bcrypt (eng keng, ishonchli):
  bcrypt.hash(password, 10)   // 10 = cost (2^10 marta — sekin)
  bcrypt.compare(password, hash)   // solishtirish

  argon2 (zamonaviy, eng kuchli — 2015 mukofot):
   xotira-og'ir (GPU/ASIC hujumga qarshi) — eng yangi tavsiya

   Parol hash — bcrypt/argon2 (ATAYIN sekin) — MD5/SHA EMAS (tez = brute force oson)
   Sekinlik — xususiyat (hujumchi har parolni sekin sinashga majbur)

Hash funksiyalari (nega bcrypt/argon2) — to'g'ri hash funksiyasini tanlash. Hash kerak, lekin qaysi hash muhim. Oddiy hash (MD5, SHA-256 — umumiy maqsadli): parol uchun xavfli — chunki ular chaqqon (tez — fayl yaxlitligi tekshirish uchun mo'ljallangan) — hujumchi sekundda millionlab parolni hash qilib sinaydi (brute force), va rainbow table (oldindan hisoblangan hash katalogi) bilan tez topadi. Tez hash — parol uchun yomon. Parol uchun maxsus hash (bcrypt, argon2, scrypt — sekin): atayin sekin (har hash millisekundlar — hujumchi sekundda kam sinaydi — brute force qiyinlashadi), cost factor (sozlanadigan sekinlik — kompyuter tezlashsa cost oshiriladi — kelajakka moslashuv), salt avtomatik (rainbow table ishlamaydi — 2.3). bcrypt (eng keng, ishonchli): bcrypt.hash(password, 10) (10 = cost factor — 2^10 marta takrorlash — sekin), bcrypt.compare(password, hash) (kirishda solishtirish). argon2 (zamonaviy, eng kuchli — 2015 Password Hashing Competition g'olibi): xotira-og'ir (ko'p xotira talab qiladi — GPU/ASIC bilan parallel hujumga qarshi — eng yangi tavsiya). Ikki nuqta: (1) parol hash — bcrypt/argon2 (atayin sekin — brute force qiyin) — MD5/SHA emas (tez = brute force oson — keng xato); (2) sekinlik — xususiyat (kamchilik emas — hujumchini har parolni sekin sinashga majbur qiladi). Ko'p dasturchi "hash ishlatdim" deb MD5/SHA ishlatadi (xato — tez hash parolni himoyalamaydi). To'g'ri — bcrypt (eng keng, oson) yoki argon2 (eng kuchli). Cost factor (bcrypt 10-12) — sekinlik balansi (xavfsizlik vs serverga yuk). Bu — parol saqlashning to'g'ri usuli (hash + sekin + salt).

2.3. Salt va pepper

text
  SALT — har parolga noyob tasodifiy qo'shimcha (rainbow table'ni yo'qotadi):

  MUAMMO (salt'siz): ikki bir xil parol  bir xil hash:
  "parol123"  "abc..." (Ali)
  "parol123"  "abc..." (Vali)   bir xil!  rainbow table topadi

  SALT bilan: har parolga noyob salt  har xil hash:
  "parol123" + salt_A  "xyz..." (Ali)
  "parol123" + salt_B  "qwe..." (Vali)   har xil!  rainbow table ishlamaydi

  bcrypt/argon2 — salt AVTOMATIK (hash ichida saqlanadi):
  $2b$10$[22-belgi-salt][hash]    salt hash'ning bir qismi (alohida saqlash kerak emas)

  PEPPER (qo'shimcha — ixtiyoriy):
   barcha parolga qo'shilgan MAXFIY qiymat (DB'da EMAS — env/HSM'da)
   DB sizsa ham — pepper'siz hash buzib bo'lmaydi (qo'shimcha qatlam)

   Salt — har parolga noyob (rainbow table'ni yo'qotadi); bcrypt/argon2 avtomatik
   Pepper — barcha parol uchun maxfiy qiymat (DB'dan tashqarida — qo'shimcha himoya)

Salt va pepper — hash'ni yanada kuchaytirish. Salt — har parolga qo'shilgan noyob tasodifiy qiymat. Muammo (salt'siz): ikki foydalanuvchi bir xil parol ("parol123") ishlatsa, ular bir xil hash ("abc...") beradi — hujumchi buni payqaydi (ikki bir xil hash = bir xil parol), va rainbow table (mashhur parollar va ularning oldindan hisoblangan hash'lari katalogi) bilan tez topadi. Salt bilan: har parolga noyob salt qo'shiladi — "parol123" + salt_A "xyz..." (Ali), "parol123" + salt_B "qwe..." (Vali) — bir xil parol, lekin har xil hash (har xil salt tufayli) rainbow table ishlamaydi (oldindan hisoblash mumkin emas — har salt noyob). bcrypt/argon2 — salt'ni avtomatik generatsiya qiladi va hash ichida saqlaydi ($2b$10$[22-belgi-salt][hash] — salt hash'ning bir qismi — alohida saqlash kerak emas — kutubxona boshqaradi). Pepper (qo'shimcha — ixtiyoriy): barcha parolga qo'shilgan maxfiy qiymat, lekin DB'da emas (env yoki HSM — Hardware Security Module — da) — agar DB sizsa ham, hujumchida pepper yo'q (u alohida joyda) pepper'siz hash'ni buzib bo'lmaydi (qo'shimcha himoya qatlami). Ikki nuqta: (1) salt — har parolga noyob (rainbow table'ni yo'qotadi — bir xil parol har xil hash) — bcrypt/argon2 buni avtomatik qiladi; (2) pepper — barcha parol uchun maxfiy qiymat (DB'dan tashqarida — qo'shimcha himoya — DB sizsa ham foyda). Yaxshi xabar — bcrypt/argon2 ishlatsangiz, salt avtomatik (siz o'ylamaysiz — bcrypt.hash o'zi salt qo'shadi). Pepper — qo'shimcha (yuqori xavfsizlik kerak bo'lganda). Salt — rainbow table hujumiga qarshi asosiy himoya (bcrypt buni beradi). Bu — hash'ni to'liq xavfsiz qiladigan qo'shimcha qatlamlar.

2.4. Parol siyosati (kuchli parol)

text
  PAROL SIYOSATI — kuchli parolni rag'batlantirish (NIST 2024 tavsiyalari):

  ZAMONAVIY (NIST) TAVSIYALAR:
   UZUNLIK muhim (kamida 8, yaxshisi 12+) — uzunlik > murakkablik
   Parol iboralarga ruxsat (passphrase — "tog quyosh daryo kitob")
   Buzilgan parollarni tekshir (Have I Been Pwned — keng buzilganlar)
   Maxsus belgi MAJBURLAMA (foydalanuvchi "Parol1!" qiladi — zaif lekin "murakkab")

  ESKI (XATO) QOIDALAR (endi tavsiya ETILMAYDI):
   Majburiy maxsus belgi/raqam (foydalanuvchi zaif naqsh yaratadi)
   Majburiy davriy o'zgartirish (90 kun — foydalanuvchi "Parol1Parol2")
   Parol maslahatlari (savol-javob — oson topiladi)

   TO'G'RI YONDASHUV:
   uzunlik (12+) + buzilgan parol tekshir + parol menejeri rag'bati
   tekshir: zlib/zxcvbn (parol kuchini baholash)

   NIST: uzunlik > murakkablik; buzilgan parol tekshir; majburiy belgi/davriy emas
   Eski qoidalar (maxsus belgi, davriy o'zgartirish) — zaif naqshga olib keladi

Parol siyosati (kuchli parol) — kuchli parolni rag'batlantirish (zamonaviy NIST tavsiyalari). Zamonaviy (NIST — AQSh standartlar instituti) tavsiyalari: (1) uzunlik muhim (kamida 8, yaxshisi 12+) — uzunlik murakkablikdan muhimroq (uzun, oddiy parol qisqa, murakkabdan kuchliroq — "tog quyosh daryo kitob" > "P@ss1!"); (2) parol iboralarga ruxsat (passphrase — bir necha so'z — eslab qolish oson, kuchli); (3) buzilgan parollarni tekshir (Have I Been Pwned API — agar parol allaqachon keng buzilganlar ro'yxatida bo'lsa, rad et); (4) maxsus belgi majburlama (foydalanuvchi "Parol1!" qiladi — texnik "murakkab", lekin zaif). Eski (xato) qoidalar (endi tavsiya etilmaydi): (1) majburiy maxsus belgi/raqam (foydalanuvchi zaif, taxmin qilinadigan naqsh yaratadi — "Parol1!"); (2) majburiy davriy o'zgartirish (90 kunda — foydalanuvchi "Parol1" "Parol2" qiladi — zaifroq); (3) parol maslahatlari (savol-javob — "onangizning qizlik familiyasi" — ijtimoiy tarmoqdan topiladi). To'g'ri yondashuv: uzunlik (12+) + buzilgan parol tekshir + parol menejeri rag'bati (kuchli, noyob parol generatsiya), kuchni baholash (zxcvbn kutubxonasi — parol qanchalik kuchli). Ikki nuqta: (1) NIST: uzunlik > murakkablik, buzilgan parol tekshir, majburiy belgi/davriy o'zgartirish emas; (2) eski qoidalar (maxsus belgi, davriy o'zgartirish) — zaif, taxmin qilinadigan naqshlarga olib keladi (teskari samara). Bu zamonaviy yondashuv (eski "murakkab parol" qoidalari yangilandi — tadqiqotlar ko'rsatdi ular zaif naqshlar yaratadi). Eng yaxshi — uzun parol/passphrase + buzilgan parol tekshir + 2FA 2.6-bob. Parol menejeri (foydalanuvchi har saytga noyob, kuchli parol) — eng yaxshi amaliyot (rag'batlantir).

2.5. Brute force himoyasi

text
  BRUTE FORCE — parolni ko'p marta sinab topish (himoya majburiy):

  HUJUM TURLARI:
   BRUTE FORCE: barcha kombinatsiyani sinash (zaif parol — soatlarda)
   DICTIONARY: keng parollar ro'yxati ("123456", "password")
   CREDENTIAL STUFFING: boshqa saytdan sizgan email/parol 2.1-bob

  HIMOYA QATLAMLARI:
  1. RATE LIMITING (so'rovni cheklash — 14.8):
   bir IP/hisob — daqiqada N urinish (keyin kutish)

  2. ACCOUNT LOCKOUT (hisobni vaqtincha bloklash):
   5 noto'g'ri urinish  15 daqiqa blok (yoki progressiv kechikish)

  3. CAPTCHA (bot emas — odam tekshiruvi):
   bir necha noto'g'ri urinishdan keyin CAPTCHA

  4. BIR XIL JAVOB (ma'lumot sizmasin):
   "email yoki parol noto'g'ri" (qaysi biri — aytma — 2.7)

  5. BUZILGAN PAROL TEKSHIR 2.4-bob + 2FA (2.6)

   Brute force — parolni sinab topish; himoya — rate limit + lockout + CAPTCHA + 2FA
   Bir IP/hisob urinish chekla (cheksiz urinish — zaif parol buziladi)

Brute force himoyasi — parolni ko'p marta sinab topishdan himoya. Hujum turlari: (1) brute force — barcha mumkin kombinatsiyani ketma-ket sinash (zaif/qisqa parol — soatlarda topiladi); (2) dictionary — keng parollar ro'yxati ("123456", "password", "qwerty" — eng ko'p ishlatiladigan) bilan sinash; (3) credential stuffing — boshqa saytdan sizgan email/parolni sinash (2.1 — ko'pincha ishlaydi — odamlar parolni qayta ishlatadi). Himoya qatlamlari: (1) rate limiting (so'rovni cheklash — 14.8): bir IP yoki hisob — daqiqada N urinish (masalan 5), keyin kutish (cheksiz urinish to'siladi); (2) account lockout (hisobni vaqtincha bloklash): 5 noto'g'ri urinishdan keyin 15 daqiqa blok (yoki progressiv kechikish — har noto'g'ri urinishda kutish vaqti oshadi — 1s, 2s, 4s, 8s... — afzalroq, chunki to'liq lockout DoS uchun ishlatilishi mumkin); (3) CAPTCHA (bot emas — odam tekshiruvi): bir necha noto'g'ri urinishdan keyin CAPTCHA (avtomatik botlarni to'sadi); (4) bir xil javob (ma'lumot sizmasin): "email yoki parol noto'g'ri" — qaysi biri xato ekanini aytma (2.7 — agar "email topilmadi" desa, hujumchi qaysi email ro'yxatda borligini biladi); (5) buzilgan parol tekshir 2.4-bob + 2FA 2.6-bob. Ikki nuqta: (1) brute force — parolni sinab topish (zaif parol himoyasiz — buziladi); himoya — rate limit + lockout + CAPTCHA + 2FA (qatlamlar); (2) bir IP/hisob urinishni chekla (cheksiz urinish — zaif parol vaqt masalasi). Eng muhim — rate limiting (14.8 — har login endpoint'ida) va 2FA (parol buzilsa ham — ikkinchi omil). Progressiv kechikish (lockout o'rniga) — DoS'dan saqlanadi (hujumchi boshqalarni bloklamasin). Credential stuffing'ga qarshi — buzilgan parol tekshir + 2FA. Brute force himoyasi — login endpoint'ining majburiy qismi (aks holda zaif parol vaqt masalasi).

2.6. 2FA / MFA (ikki bosqichli)

text
  2FA/MFA — paroldan tashqari IKKINCHI omil (parol buzilsa ham himoya):

  UCH OMIL TURI ("nimani bilasiz/bordingiz/sizmiz"):
  1. BILASIZ — parol, PIN
  2. BORINGIZDA — telefon (SMS/app), xavfsizlik kaliti (YubiKey)
  3. SIZMIZ — barmoq izi, yuz (biometrik)
   2FA = ikki HAR XIL tur (parol + telefon)

  USULLAR (xavfsizlik tartibi):
   TOTP (authenticator app — Google Authenticator, 6 raqam, 30s) — yaxshi
   Hardware key (YubiKey, WebAuthn/passkey) — ENG XAVFSIZ (phishing'ga chidamli)
   SMS — qulay, lekin zaifroq (SIM swap, ushlab olish) — yo'qdan yaxshi

  NEGA 2FA:
   parol buzilsa (sizish, brute force, phishing) ham — ikkinchi omil to'sadi
   hisob egallashni keskin kamaytiradi (eng samarali himoya)

   2FA — ikkinchi omil (parol + telefon/app) — parol buzilsa ham hisob himoyalangan
   TOTP/hardware key (SMS'dan yaxshi); 2FA — eng samarali hisob himoyasi

2FA / MFA (ikki bosqichli) — paroldan tashqari ikkinchi himoya omili. 2FA (Two-Factor Authentication) / MFA (Multi-Factor) — autentifikatsiyaga ikkinchi omil qo'shish (parol + yana bir narsa). Uch omil turi ("nimani bilasiz / nimaga egasiz / kimsiz"): (1) bilasiz — parol, PIN (xotirada); (2) egasiz — telefon (SMS yoki authenticator app), xavfsizlik kaliti (YubiKey — jismoniy qurilma); (3) kimsiz — barmoq izi, yuz (biometrik). 2FA = ikki har xil tur (masalan parol — bilasiz + telefon — egasiz). Usullar (xavfsizlik tartibi): (1) TOTP (Time-based One-Time Password — authenticator app — Google Authenticator, Authy — 6 raqamli kod, har 30 soniyada yangilanadi) — yaxshi (telefonda, internetsiz ishlaydi); (2) hardware key (YubiKey, WebAuthn/passkey — jismoniy kalit yoki qurilma biometrikasi) — eng xavfsiz (phishing'ga chidamli — soxta saytga ishlamaydi); (3) SMS — qulay, lekin zaifroq (SIM swap — hujumchi telefon raqamini o'g'irlaydi, SMS ushlab olish — lekin yo'qdan yaxshi). Nega 2FA: parol buzilsa (sizish — 2.1, brute force — 2.5, phishing) ham — hujumchida ikkinchi omil yo'q (telefon/kalit) hisobga kira olmaydi 2FA hisob egallashni keskin kamaytiradi (eng samarali himoya). Ikki nuqta: (1) 2FA — ikkinchi omil (parol + telefon/app) — parol buzilsa ham hisob himoyalangan (eng katta zarar — hisob egallash — to'siladi); (2) TOTP/hardware key (SMS'dan yaxshi — SIM swap'ga chidamli), 2FA — eng samarali hisob himoyasi. 2FA — zamonaviy autentifikatsiyaning standarti (banklar, muhim xizmatlar majburiy qiladi). Hatto parol zaif yoki sizgan bo'lsa ham — 2FA hisobni himoyalaydi. WebAuthn/passkey — kelajak (parolsiz, phishing'ga chidamli — eng xavfsiz). 2FA'ni taklif qilish (yoki muhim hisoblarga majburlash) — autentifikatsiya xavfsizligining eng katta yaxshilanishi.

2.7. Sessiya xavfsizligi va auth xatolari

text
  SESSIYA XAVFSIZLIGI va KENG AUTH XATOLARI:

  SESSIYA XAVFSIZLIGI:
   Login'dan keyin yangi sessiya ID (session fixation oldini)
   HttpOnly + Secure + SameSite cookie (XSS/CSRF — 14.2, 14.4)
   Sessiya muddati (maxAge) + faolsizlik timeout
   Logout — sessiyani BUTUNLAY bekor (server'da ham)
   Muhim amal (parol o'zgartirish) — qayta parol so'rash

  KENG AUTH XATOLARI:
   "Email topilmadi" vs "Parol noto'g'ri" (user enumeration — qaysi email bor)
     BIR XIL javob: "Email yoki parol noto'g'ri"
   Parol tiklash token zaif/muddatsiz (14.1: Misol 3)
   JWT secret zaif / token muddatsiz 14.6-bob
   Default/test hisoblar (admin/admin — production'da)
   Parolni URL/logda (GET parol — log'da saqlanadi)

   Sessiya — yangi ID (login), HttpOnly cookie, muddat, to'liq logout
   User enumeration oldini — bir xil javob (email bor/yo'q oshkor qilma)

Sessiya xavfsizligi va auth xatolari — autentifikatsiyani to'liq xavfsiz qilish. Sessiya xavfsizligi: (1) login'dan keyin yangi sessiya ID (session fixation hujumini oldini — hujumchi oldindan sessiya ID berib, foydalanuvchi kirsa o'sha ID bilan egallashi mumkin — login'da yangi ID berish buni to'sadi); (2) HttpOnly + Secure + SameSite cookie (XSS — 14.2 — JS o'qiy olmaydi; CSRF — 14.4 — boshqa saytdan yuborilmaydi); (3) sessiya muddati (maxAge) + faolsizlik timeout (uzoq faolsizlikdan keyin chiqarish); (4) logout — sessiyani butunlay bekor qilish (server'da ham — JWT bo'lsa qora ro'yxat yoki qisqa muddat — 14.6); (5) muhim amal (parol o'zgartirish, to'lov) — qayta parol so'rash (sessiya o'g'irlansa ham — muhim amal qo'shimcha tasdiq). Keng auth xatolari: (1) user enumeration — "Email topilmadi" vs "Parol noto'g'ri" (har xil javob — hujumchi qaysi email ro'yxatda borligini biladi) bir xil javob ("Email yoki parol noto'g'ri" — qaysi biri xato — aytma); (2) parol tiklash token zaif/muddatsiz (14.1: Misol 3); (3) JWT secret zaif / token muddatsiz 14.6-bob; (4) default/test hisoblar (admin/admin — production'da qoldirilgan); (5) parolni URL yoki log'da (GET so'rovda parol — server log'ida saqlanadi — sizadi). Ikki nuqta: (1) sessiya — yangi ID (login — session fixation), HttpOnly cookie, muddat, to'liq logout; (2) user enumeration oldini — bir xil javob (email bor/yo'qligini oshkor qilma — hujumchiga ma'lumot berma). Bu xatolar — autentifikatsiyaning nozik, lekin muhim qismlari (asosiy — parol hash, lekin bu detallar ham muhim). Auth.js 13.9-bob ko'p sessiya xavfsizligini avtomatik qiladi (yangi ID, HttpOnly, CSRF), lekin user enumeration, parol siyosati, 2FA — siz qo'shasiz. Autentifikatsiya — ko'p qatlamli (parol hash + brute force himoya + 2FA + sessiya xavfsizligi + xatolardan qochish) — har biri muhim.

2.8. JWT xavfsizligi va OAuth/OIDC

text
  JWT (JSON Web Token) — imzolangan token bilan autentifikatsiya (nozik xavflar):

  IMZO ALGORITMI:
   HS256 (simmetrik — bir maxfiy kalit imzolaydi va tekshiradi)
   RS256 (asimmetrik — private kalit imzolaydi, public tekshiradi — mikroservis)
   alg:none HUJUMI — token header'ida "alg":"none"  imzo tekshirilmasa qalbaki qabul
   server kutgan algoritmni MAJBURLA (client tanlashiga ishonma)

  KALIT / SECRET:
   zaif secret ("secret", "123")  brute force  istalgan token soxtalashtiriladi
   kuchli tasodifiy secret (32+ bayt), env'da 14.6-bob, kod'da EMAS

  MUDDAT VA REFRESH:
   access token QISQA (5–15 daqiqa — sizsa ham tez tugaydi)
   refresh token uzoq + ROTATION (har ishlatishda yangisi, eskisi bekor)
   refresh rotation'siz  o'g'irlangan refresh cheksiz ishlaydi

  SAQLASH (storage):
   localStorage  XSS 14.2-bob token'ni o'qiy oladi (JS'ga ochiq)
   httpOnly + Secure + SameSite cookie (JS o'qiy olmaydi — XSS himoya)

  REVOCATION (bekor qilish muammosi):
   JWT stateless  logout'da darrov bekor bo'lmaydi (server eslamaydi)
   qisqa exp + refresh + qora ro'yxat (jti) yoki token versiyasi

   JWT: server algoritmni majburla (alg:none yo'q); kuchli secret; qisqa exp
   refresh rotation; httpOnly cookie (localStorage emas); revocation rejasi

JWT xavfsizligi va OAuth/OIDC — token asosidagi autentifikatsiyaning nozik xavflari (chuqur — 14.6). JWT (JSON Web Token) — imzolangan, o'zi-ma'lumot saqlaydigan token (sessiya o'rniga ko'p ishlatiladi). U qulay, lekin noto'g'ri ishlatilsa jiddiy zaiflik. Imzo algoritmi: HS256 (simmetrik — bitta maxfiy kalit ham imzolaydi, ham tekshiradi — bir server uchun oddiy), RS256 (asimmetrik — private kalit imzolaydi, public kalit tekshiradi — mikroservislar uchun: tekshiruvchilar faqat public kalitni oladi, imzolay olmaydi). alg:none hujumi — JWT standarti "alg":"none" (imzosiz) qiymatini qabul qiladi; agar kutubxona buni rad qilmasa, hujumchi imzosiz, ixtiyoriy payload (masalan role: admin) bilan token yasaydi va server uni qabul qiladi — himoya: server kutgan algoritmni majburla ({ algorithms: ["HS256"] } — client header'idagi alg'ga ishonma). Yana bir hujum: RS256 kutgan server HS256'ga aldansa — hujumchi public kalitni HMAC secret sifatida ishlatib token imzolaydi (algoritmni qattiq belgilash buni ham to'sadi). Kalit/secret: zaif secret ("secret", "123") — hashcat/brute force bilan topiladi hujumchi istalgan token yasaydi; kuchli tasodifiy secret (32+ bayt — randomBytes), env'da (14.6 — kod'da yozma). Muddat va refresh: access token qisqa (5–15 daqiqa — o'g'irlansa ham tez tugaydi), refresh token uzoq muddatli, lekin rotation bilan (har ishlatishda yangi refresh beriladi, eskisi bekor qilinadi — o'g'irlangan refresh ikkinchi marta ishlatilsa, aniqlanadi va butun zanjir bekor bo'ladi). Saqlash (storage — muhim tanlov): localStorageXSS 14.2-bob orqali JS token'ni o'qiy oladi (istalgan inject qilingan skript token'ni o'g'irlaydi); httpOnly cookie (+ Secure + SameSite) — JS o'qiy olmaydi (XSS token'ni ololmaydi), lekin CSRF 14.4-bob uchun SameSite/CSRF token kerak. Revocation (JWT muammosi): JWT stateless (server holatni eslamaydi) logout'da token darrov bekor bo'lmaydi (muddati tugaguncha amal qiladi); yechim: qisqa exp + refresh, yoki qora ro'yxat (jti — token ID'sini bekor qilinganlar ro'yxatiga qo'shish), yoki foydalanuvchi "token versiyasi" (parol o'zgarsa versiya oshadi — eski tokenlar bekor). Ikki nuqta: (1) JWT — server algoritmni majburla (alg:none va HS/RS aldashini to's), kuchli secret, qisqa exp; (2) refresh rotation, httpOnly cookie (localStorage emas), revocation rejasi. OAuth 2.0 / OIDC (uchinchi tomon bilan kirish — "Google bilan kirish"): (1) state parametri — CSRF 14.4-bob himoyasi (so'rov va javob mosligini tekshir — hujumchi o'z akkauntini ulab qo'ymasin); (2) PKCE (Proof Key for Code Exchange) — kod almashinuvini himoyalaydi (public client — mobil/SPA — uchun majburiy — o'g'irlangan authorization code ishlamaydi); (3) redirect_uri validatsiya — faqat oldindan ro'yxatga olingan URL'ga qaytar (ochiq redirect token o'g'irlik). Passwordless (parolsiz — magic link yoki passkey/WebAuthn): parol umuman yo'q (magic link — emailga bir martalik xavfsiz havola, yoki WebAuthn — 2.6 — phishing'ga chidamli) — parol zaifliklari (sizish, brute force, qayta ishlatish) butunlay yo'qoladi (kelajak yo'nalishi). Concurrent session (bir vaqtda ko'p sessiya): foydalanuvchining faol sessiyalarini ko'rsatish va boshqasini uzoqdan chiqarish imkoni (o'g'irlangan sessiyani foydalanuvchi o'zi to'xtata olsin). Bu — zamonaviy token/kirish xavfsizligining to'liq manzarasi (chuqur amaliyot — 14.6).


3. Sintaksis — tez ma'lumotnoma

text
HASH 2.2-bob:         bcrypt.hash(password, 10)  |  argon2.hash(password)
COMPARE 2.2-bob:      bcrypt.compare(password, hash)    true/false
SALT 2.3-bob:         bcrypt/argon2 avtomatik (hash ichida)
SIYOSAT 2.4-bob:      uzunlik 12+, buzilgan parol tekshir (zxcvbn, HIBP)
RATE LIMIT 2.5-bob:   login — daqiqada N urinish 14.8-bob
2FA 2.6-bob:          TOTP (authenticator), WebAuthn (passkey)
SESSIYA 2.7-bob:      login  yangi ID; HttpOnly+Secure+SameSite; logout  bekor
JAVOB 2.7-bob:        "Email yoki parol noto'g'ri" (enumeration oldini)
JWT 2.8-bob:          jwt.verify(t, secret, { algorithms: ["HS256"] })  |  exp qisqa
OAUTH 2.8-bob:        state (CSRF) + PKCE + redirect_uri validatsiya

4. Batafsil misollar

Har misol: Maqsad + izohli kod + "Bu nima qiladi".

Misol 1 — Parol hash va tekshirish (bcrypt — 2.1, 2.2)

Maqsad: Ro'yxat va login'da parolni bcrypt bilan xavfsiz saqlash va tekshirish. Bu autentifikatsiyaning eng asosiy amali.

tsx
import bcrypt from "bcryptjs";

// RO'YXAT — parolni HASH qilib saqlash (ochiq EMAS):
async function register(email: string, password: string) {
  // 1. bcrypt hash (salt avtomatik, cost 12 — sekin):
  const passwordHash = await bcrypt.hash(password, 12);

  // 2. DB'ga HASH saqlanadi (ochiq parol HECH QAERDA):
  await db.user.create({ data: { email, passwordHash } });
  //  DB'da: passwordHash = "$2b$12$N9qo8uLOick..." (asl parol yo'q)
}

// LOGIN — parolni HASH bilan solishtirish:
async function login(email: string, password: string) {
  const user = await db.user.findUnique({ where: { email } });

  //  Bir xil javob (user yo'q yoki parol noto'g'ri — farqlama — 2.7):
  if (!user) {
    await bcrypt.hash(password, 12);   // vaqt hujumi oldini (user yo'q bo'lsa ham vaqt sarf)
    return null;
  }

  // bcrypt.compare — kiritilgan parolni hash bilan solishtirish:
  const valid = await bcrypt.compare(password, user.passwordHash);
  return valid ? user : null;   // bir xil javob (qaysi biri xato — aytma)
}

Bu nima qiladi: Bu — parol hash va tekshirish (autentifikatsiyaning eng asosiy amali — 2.1, 2.2). Ro'yxat: (1) bcrypt.hash(password, 12) — parolni hash qiladi (12 — cost factor — sekin — 2.2; salt avtomatik — 2.3); (2) DB'ga hash saqlanadi (passwordHash"$2b$12$..."asl parol hech qaerda saqlanmaydi). Endi DB sizsa ham — hujumchi hash'ni ko'radi, asl parolni ola olmaydi (bir tomonlama — 2.1). Login: (1) email bo'yicha foydalanuvchini topish; (2) bcrypt.compare(password, user.passwordHash) — kiritilgan parolni DB'dagi hash bilan solishtirish (bcrypt parolni hash qilib, saqlangan hash bilan taqqoslaydi — true/false; bcrypt asl parolni tiklamaydi — faqat solishtiradi); to'g'ri bo'lsa foydalanuvchi, aks holda null. Ikki nozik xavfsizlik nuqtasi: (1) bir xil javob 2.7-bob — user yo'q ham, parol noto'g'ri ham null (qaysi biri xato — aytma — user enumeration oldini); (2) vaqt hujumi (timing attack) oldini — agar user yo'q bo'lsa darrov null qaytarsak, hujumchi javob vaqtiga qarab (tez = user yo'q, sekin = bcrypt.compare ishladi = user bor) email mavjudligini biladi — shuning uchun user yo'q bo'lsa ham bcrypt.hash (yoki dummy compare) bilan vaqt sarflaymiz (har holda bir xil vaqt — enumeration oldini). Demak: parol hash (bcrypt — sekin, salt) + bir xil javob + vaqt tenglashtirish. Hech qachon ochiq parol saqlama (password: "..."), MD5/SHA ishlatma (tez — 2.2), to'g'ri/noto'g'ri javobni farqlama (enumeration). bcrypt — eng oson, ishonchli (yoki argon2 — kuchliroq). Bu — har ro'yxat/login'ning poydevori.

Misol 2 — Brute force himoyasi (rate limit + lockout — 2.5)

Maqsad: Login'ni brute force'dan himoyalash — rate limiting va progressiv kechikish. Bu zaif parolni ham himoyalaydi.

tsx
// Oddiy login urinish hisobchisi (production'da Redis — 5.21):
const attempts = new Map<string, { count: number; lockedUntil?: number }>();

async function login(email: string, password: string, ip: string) {
  const key = `${ip}:${email}`;
  const record = attempts.get(key) ?? { count: 0 };

  // 1. LOCKOUT tekshir (juda ko'p urinish):
  if (record.lockedUntil && Date.now() < record.lockedUntil) {
    throw new Error("Juda ko'p urinish. Keyinroq qayta urining.");
  }

  // 2. Parol tekshir (Misol 1):
  const user = await db.user.findUnique({ where: { email } });
  const valid = user && (await bcrypt.compare(password, user.passwordHash));

  if (!valid) {
    // 3. Noto'g'ri — hisobchini oshir + progressiv kechikish:
    record.count++;
    if (record.count >= 5) {
      record.lockedUntil = Date.now() + 15 * 60 * 1000;   // 15 daqiqa blok
    }
    attempts.set(key, record);
    await new Promise((r) => setTimeout(r, record.count * 1000));   // progressiv kechikish
    return null;
  }

  // 4. To'g'ri — hisobchini tozala:
  attempts.delete(key);
  return user;
}

Bu nima qiladi: Bu — brute force himoyasi (rate limit + progressiv kechikish — 2.5). Login endpoint'ini ko'p marta sinashdan himoya. Mexanizm: har ip:email uchun urinishlarni hisoblaydi. (1) lockout tekshir — agar hisob bloklangan bo'lsa (lockedUntil — juda ko'p urinish) va vaqt o'tmagan bo'lsa — rad ("Juda ko'p urinish"); (2) parol tekshir (Misol 1 — bcrypt); (3) agar noto'g'ri — hisobchini oshiradi (count++), 5 urinishdan keyin 15 daqiqa bloklaydi (lockedUntil), va progressiv kechikish (setTimeout(record.count * 1000) — har noto'g'ri urinishda kutish oshadi — 1s, 2s, 3s... — brute force sekinlashadi); (4) agar to'g'ri — hisobchini tozalaydi (muvaffaqiyatli login — qayta boshlash). Nega bu kerak: rate limit/lockout'siz, hujumchi cheksiz urinish qila oladi (sekundda minglab) — zaif parol vaqt masalasi (buziladi). Rate limit bilan — bir hisob/IP daqiqada bir necha urinish (brute force amaliy emas — yillar kerak). Progressiv kechikish (to'liq lockout o'rniga) afzal — chunki to'liq lockout DoS uchun ishlatilishi mumkin (hujumchi boshqa foydalanuvchilarni ataylab bloklaydi — 5 noto'g'ri urinish bilan). Progressiv kechikish sekinlashtiradi, lekin to'liq bloklamaydi. Production'da — bu hisobchini Redisda (5.21 — server qayta ishga tushsa ham qoladi, ko'p server uchun umumiy) yoki maxsus kutubxona (express-rate-limit, Upstash — 14.8). Bu oddiy misol (Map — bitta server, demo). Brute force himoyasi — har login endpoint'ining majburiy qismi (rate limit + 2FA — zaif parolni ham himoyalaydi). 14.8'da rate limiting chuqurroq (umumiy himoya).

Misol 3 — Buzilgan parol tekshir (HIBP — 2.4)

Maqsad: Ro'yxatda buzilgan (keng sizgan) parolni rad qilish — Have I Been Pwned bilan. Bu credential stuffing'ga qarshi.

tsx
import { createHash } from "crypto";

// Parol allaqachon buzilganlar ro'yxatidami? (HIBP k-anonymity — parol YUBORILMAYDI):
async function isPasswordBreached(password: string): Promise<boolean> {
  // 1. SHA-1 hash (HIBP formati):
  const hash = createHash("sha1").update(password).digest("hex").toUpperCase();
  const prefix = hash.slice(0, 5);    // faqat birinchi 5 belgi yuboriladi
  const suffix = hash.slice(5);

  // 2. HIBP API (k-anonymity — faqat prefix yuboriladi, parol YO'Q):
  const res = await fetch(`https://api.pwnedpasswords.com/range/${prefix}`);
  const text = await res.text();

  // 3. Javobda suffix bormi (parol buzilgan)?
  return text.split("\n").some((line) => line.split(":")[0] === suffix);
}

// RO'YXATDA:
async function register(email: string, password: string) {
  if (password.length < 12) throw new Error("Parol kamida 12 belgi");
  if (await isPasswordBreached(password)) {
    throw new Error("Bu parol keng buzilganlar ro'yxatida. Boshqa parol tanlang.");
  }
  const passwordHash = await bcrypt.hash(password, 12);
  await db.user.create({ data: { email, passwordHash } });
}

Bu nima qiladi: Bu — buzilgan parolni tekshirish (HIBP — 2.4 — credential stuffing'ga qarshi). Muammo: foydalanuvchi paroli allaqachon boshqa saytdan sizgan va keng "buzilganlar" ro'yxatida bo'lishi mumkin ("123456", yoki murakkab ko'ringan, lekin sizgan parol) — bunday parol zaif (hujumchi dictionary'da bor). Have I Been Pwned (HIBP) — milliardlab sizgan parol ma'lumotlar bazasi (API bilan tekshirsa bo'ladi). isPasswordBreached: (1) parolni SHA-1 hash qiladi (HIBP formati); (2) k-anonymity — faqat hash'ning birinchi 5 belgisini (prefix) HIBP'ga yuboradi (parol yoki to'liq hash yuborilmaydi — maxfiylik — HIBP sizning parolingizni bilmaydi); (3) HIBP shu prefix bilan boshlangan barcha buzilgan hash'larni qaytaradi, va kod mahalliy (client'da) suffix'ni solishtiradi (parol ro'yxatdami). Ro'yxatda: uzunlik tekshir (12+ — 2.4) + buzilgan parol tekshir (agar buzilgan — rad: "Bu parol keng buzilganlar ro'yxatida") + bcrypt hash (Misol 1). Nega muhim: kuchli ko'ringan parol ham, agar sizgan bo'lsa, zaif (hujumchi uni dictionary/credential stuffing'da sinaydi). HIBP tekshiruvi bunday parollarni rad qiladi (foydalanuvchi noyob, sizmagan parol tanlashga majbur). k-anonymity — bu tekshiruvni maxfiy qiladi (parolni HIBP'ga yubormasdan — faqat prefix — HIBP qaysi parolni tekshirayotganingizni bilmaydi). Bu — zamonaviy parol siyosatining qismi (murakkablik qoidalari o'rniga — uzunlik + buzilgan parol tekshir — 2.4 NIST). Credential stuffing (sizgan parol qayta ishlatish) — eng keng hujumlardan — HIBP tekshiruvi unga qarshi (sizgan parol — rad). Oson qo'shiladigan, samarali himoya.

Misol 4 — TOTP 2FA (2.6)

Maqsad: TOTP (authenticator app) bilan 2FA qo'shish — parol buzilsa ham himoya. Bu eng samarali hisob himoyasi.

tsx
import { authenticator } from "otplib";
import QRCode from "qrcode";

// 1. 2FA SOZLASH — secret yaratish + QR kod (foydalanuvchi app'da skanerlaydi):
async function setup2FA(userId: string, email: string) {
  const secret = authenticator.generateSecret();   // noyob secret (DB'da saqlanadi)
  await db.user.update({ where: { id: userId }, data: { totpSecret: secret } });

  // QR kod (Google Authenticator/Authy skanerlaydi):
  const otpauth = authenticator.keyuri(email, "MyApp", secret);
  return QRCode.toDataURL(otpauth);   // QR rasm — foydalanuvchiga ko'rsatiladi
}

// 2. LOGIN'DA 2FA tekshir (parol to'g'ri bo'lgandan KEYIN):
async function verify2FA(userId: string, code: string): Promise<boolean> {
  const user = await db.user.findUnique({ where: { id: userId } });
  if (!user?.totpSecret) return false;

  // App'dagi 6 raqamli kod (30s) to'g'rimi:
  return authenticator.verify({ token: code, secret: user.totpSecret });
}

// LOGIN OQIMI:
// 1. Email/parol tekshir (Misol 1)  to'g'ri
// 2. 2FA yoqilganmi?  ha  6 raqamli kod so'ra
// 3. verify2FA(code)  to'g'ri  sessiya yaratiladi (faqat ikki omildan keyin)

Bu nima qiladi: Bu — TOTP 2FA (authenticator app — 2.6 — eng samarali hisob himoyasi). TOTP (Time-based One-Time Password) — authenticator app (Google Authenticator, Authy) generatsiya qiladigan 6 raqamli, har 30 soniyada yangilanadigan kod. 1. Sozlash: (1) authenticator.generateSecret() — foydalanuvchi uchun noyob secret (DB'da saqlanadi — bu secret asosida kodlar generatsiya bo'ladi); (2) authenticator.keyuri(...) — secret'ni otpauth:// URL'iga aylantiradi, va QRCode.toDataURL — QR kod rasm (foydalanuvchi authenticator app'da skanerlaydi — app shu secret'ni saqlaydi va kodlar generatsiya qiladi). 2. Login'da tekshir: parol to'g'ri bo'lgandan keyin (birinchi omil), foydalanuvchidan 6 raqamli kod so'raladi, authenticator.verify({ token: code, secret }) — kiritilgan kod app'dagi kod bilan mos keladimi (server va app bir xil secret + vaqt asosida bir xil kod hisoblaydi — internetsiz, sinxron). Login oqimi: email/parol tekshir (Misol 1) to'g'ri 2FA yoqilganmi ha 6 raqamli kod so'ra verify2FA to'g'ri endi sessiya yaratiladi (faqat ikki omildan keyin — parol + TOTP kod). Nega 2FA eng samarali: agar hujumchi parolni bilsa (sizish, brute force, phishing) ham — unda authenticator app yo'q (foydalanuvchi telefonida) 6 raqamli kodni bilmaydi hisobga kira olmaydi. 2FA hisob egallashni keskin kamaytiradi (eng katta himoya). TOTP SMS'dan yaxshi (2.6 — SIM swap'ga chidamli, internetsiz). Backup kodlar (foydalanuvchi telefonini yo'qotsa — zaxira kodlar) ham kerak. WebAuthn/passkey — yanada xavfsiz (phishing'ga to'liq chidamli). 2FA'ni taklif qilish (yoki muhim hisoblarga majburlash) — autentifikatsiyaning eng katta yaxshilanishi (parol zaif bo'lsa ham himoya).

Misol 5 — Xavfsiz parol tiklash (2.7, 14.1: Misol 3)

Maqsad: Parol tiklashni xavfsiz qilish — kuchli token, muddat, bir martalik, enumeration oldini. Bu klassik auth zaiflik nuqtasi.

tsx
import { randomBytes, createHash } from "crypto";

// 1. TIKLASH SO'RAB — kuchli token yaratish:
async function requestReset(email: string) {
  const user = await db.user.findUnique({ where: { email } });

  //  BIR XIL javob (email bor/yo'q — oshkor qilma — enumeration — 2.7):
  if (user) {
    const token = randomBytes(32).toString("hex");   // kuchli tasodifiy (taxmin qilib bo'lmaydi)
    const tokenHash = createHash("sha256").update(token).digest("hex");   // DB'da HASH (token emas)
    await db.user.update({
      where: { id: user.id },
      data: { resetTokenHash: tokenHash, resetExpires: new Date(Date.now() + 30 * 60 * 1000) },  // 30 daqiqa
    });
    await sendEmail(email, `Tiklash: https://app.com/reset?token=${token}`);   // token emailda
  }
  // Har holda bir xil javob:
  return { message: "Agar email mavjud bo'lsa, tiklash havolasi yuborildi." };
}

// 2. TOKEN bilan parol o'zgartirish:
async function resetPassword(token: string, newPassword: string) {
  const tokenHash = createHash("sha256").update(token).digest("hex");
  const user = await db.user.findFirst({
    where: { resetTokenHash: tokenHash, resetExpires: { gt: new Date() } },   // muddat tekshir
  });
  if (!user) throw new Error("Havola yaroqsiz yoki muddati tugagan");

  const passwordHash = await bcrypt.hash(newPassword, 12);
  await db.user.update({
    where: { id: user.id },
    data: { passwordHash, resetTokenHash: null, resetExpires: null },   // token BIR MARTALIK (tozala)
  });
}

Bu nima qiladi: Bu — xavfsiz parol tiklash (klassik auth zaiflik nuqtasi — 2.7, 14.1: Misol 3 threat model). Parol tiklash — noto'g'ri qilinsa hisob egallash usuli. 1. Tiklash so'rash: (1) bir xil javob (enumeration oldini — 2.7) — email bor yoki yo'q, har holda "Agar email mavjud bo'lsa, havola yuborildi" (hujumchiga qaysi email ro'yxatda borligini aytma); (2) kuchli tokenrandomBytes(32) (32 bayt tasodifiy — taxmin qilib bo'lmaydi — zaif token — masalan Math.random yoki ketma-ket ID — xavfli); (3) token DB'da HASH holda (createHash("sha256") — token'ning o'zi emas, hash — agar DB sizsa, tiklash tokenlari ham himoyalangan — xuddi parol kabi); (4) muddat (resetExpires — 30 daqiqa — eski token o'g'irlansa ishlamaydi); (5) token email orqali (?token=...). 2. Token bilan o'zgartirish: (1) token'ni hash qilib DB'dan topish (resetTokenHash + resetExpires > now — muddat tekshir); (2) topilmasa rad ("yaroqsiz yoki muddati tugagan"); (3) yangi parolni bcrypt hash; (4) token'ni bir martalik qilish (resetTokenHash: null — ishlatilgach bekor — qayta ishlatib bo'lmaydi). Xavfsizlik nuqtalari (threat model — 14.1: Misol 3): kuchli token (taxmin qilib bo'lmaydi), muddat (30 daqiqa), bir martalik (ishlatilgach bekor), DB'da hash (sizsa himoyalangan), enumeration oldini (bir xil javob). Bu klassik zaiflik (ko'p sayt zaif token, muddatsiz, enumeration qiladi). Token'ni DB'da hash qilish — nozik, lekin muhim (parol kabi — token ham maxfiy). Bu — to'liq xavfsiz parol tiklash oqimi (har xavf hisobga olingan).

Misol 6 — Xavfsiz JWT (algoritm majburlash + refresh rotation — 2.8)

Maqsad: JWT'ni xavfsiz yaratish va tekshirish — algoritmni majburlash (alg:none oldini), qisqa access + refresh rotation. Bu token asosidagi auth'ning nozik nuqtalari.

tsx
import jwt from "jsonwebtoken";
import { randomBytes } from "crypto";

const SECRET = process.env.JWT_SECRET!;   // kuchli tasodifiy (32+ bayt), env'da — kod'da EMAS

// 1. ACCESS token — QISQA muddat (sizsa ham tez tugaydi):
function issueAccessToken(userId: string, tokenVersion: number) {
  return jwt.sign({ sub: userId, ver: tokenVersion }, SECRET, {
    algorithm: "HS256",
    expiresIn: "15m",   //  qisqa (5–15 daqiqa) — uzoq token o'g'irlansa xavfli
  });
}

// 2. TEKSHIRISH — algoritmni MAJBURLA (alg:none va aldashni to'sadi):
function verifyAccessToken(token: string) {
  //  jwt.verify(token, SECRET)  — client "alg" tanlashiga ishonadi (alg:none xavfi)
  //  algoritmni qattiq belgila — faqat HS256 qabul qilinadi:
  return jwt.verify(token, SECRET, { algorithms: ["HS256"] }) as {
    sub: string;
    ver: number;
  };
}

// 3. REFRESH token — uzoq, lekin ROTATION bilan (DB'da hash saqlanadi):
async function rotateRefreshToken(oldToken: string) {
  const oldHash = hashToken(oldToken);
  const stored = await db.refreshToken.findUnique({ where: { hash: oldHash } });

  //  Ishlatilgan yoki noma'lum refresh  butun zanjirni bekor qil (o'g'irlik alomati):
  if (!stored || stored.used) {
    if (stored) await db.refreshToken.deleteMany({ where: { userId: stored.userId } });
    throw new Error("Refresh token yaroqsiz — qayta kiring");
  }

  await db.refreshToken.update({ where: { hash: oldHash }, data: { used: true } });
  const newToken = randomBytes(32).toString("hex");
  await db.refreshToken.create({
    data: { hash: hashToken(newToken), userId: stored.userId, used: false },
  });
  return newToken;   // yangi refresh — eskisi bekor (rotation)
}

Bu nima qiladi: Bu — xavfsiz JWT (2.8 — token asosidagi auth'ning nozik nuqtalari; chuqur amaliyot 14.6). 1. Access tokenjwt.sign bilan yaratiladi, expiresIn: "15m"qisqa muddat (o'g'irlansa ham tez tugaydi — uzoq token xavfli), payload'da sub (user ID) va ver (token versiyasi — parol o'zgarsa oshadi, eski tokenlar bekor bo'ladi — revocation). 2. Tekshirish — bu eng muhim xavfsizlik nuqtasi: jwt.verify(token, SECRET, { algorithms: ["HS256"] }) — server kutgan algoritmni majburlaydi. Agar oddiy jwt.verify(token, SECRET) ishlatilsa, kutubxona token header'idagi alg'ga ishonadi — hujumchi "alg":"none" (imzosiz) yoki RS256HS256 aldashi bilan qalbaki token yuborishi mumkin. Algoritmni qattiq belgilash bu hujumlarni to'sadi. 3. Refresh rotation — refresh token uzoq muddatli, lekin har ishlatishda yangisiga almashtiriladi (used: true belgilanadi, yangi token beriladi). Agar allaqachon ishlatilgan (used) refresh qayta kelsa — bu o'g'irlik alomati (asl foydalanuvchi ham, o'g'ri ham bir tokenni ishlatmoqda) butun zanjir bekor qilinadi (deleteMany — foydalanuvchi qayta kirishga majbur). Refresh token DB'da hash holda saqlanadi (parol/tiklash tokeni kabi — 2.3, Misol 5 — sizsa himoyalangan). Xavfsizlik nuqtalari: algoritm majburlash (alg:none/aldash oldini), kuchli secret env'da (kod'da emas), qisqa access exp, refresh rotation (o'g'irlik aniqlash), token DB'da hash. Saqlash 2.8-bob: bu tokenlarni brauzerda localStorage'da emas, httpOnly cookie'da saqlang (XSS — 14.2 — token'ni o'qiy olmaydi). Bu — zamonaviy JWT auth'ning xavfsiz asosi (14.6'da to'liqroq).


5. To'g'ri va noto'g'ri holatlar

1) Parol saqlash

text
 ochiq yoki MD5/SHA (Misol 1, 2.2)
 bcrypt/argon2 (sekin, salt)

2) Login javobi

text
 "Email topilmadi" / "Parol noto'g'ri" (enumeration)
 "Email yoki parol noto'g'ri" (bir xil — 2.7)

3) Brute force

text
 cheksiz urinish (zaif parol buziladi)
 rate limit + lockout (Misol 2)

4) Parol siyosati

text
 majburiy maxsus belgi (zaif naqsh — 2.4)
 uzunlik 12+ + buzilgan parol tekshir (Misol 3)

5) 2FA

text
 faqat parol (sizsa hisob egallandi)
 2FA (TOTP/passkey — Misol 4)

6) Tiklash token

text
 zaif/muddatsiz/qayta ishlatiladigan (Misol 5)
 kuchli + muddat + bir martalik + hash

7) JWT tekshirish

text
 jwt.verify(t, secret) — alg:none xavfi; localStorage'da saqlash (XSS)
 algoritm majburla + qisqa exp + refresh rotation + httpOnly cookie (Misol 6, 2.8)

6. Keng tarqalgan xatolar va yechimlari

Xato 1 — Parol ochiq yoki MD5/SHA bilan

Sababi: noto'g'ri hash 2.2-bob. Yechimi: bcrypt/argon2 (Misol 1).

Xato 2 — User enumeration (email bor/yo'q oshkor)

Sababi: har xil javob 2.7-bob. Yechimi: bir xil javob + vaqt tenglashtirish (Misol 1).

Xato 3 — Brute force himoyasi yo'q

Sababi: cheksiz urinish 2.5-bob. Yechimi: rate limit + lockout (Misol 2).

Xato 4 — Eski parol qoidalari (maxsus belgi, davriy)

Sababi: zaif naqsh 2.4-bob. Yechimi: uzunlik + buzilgan parol tekshir (Misol 3).

Xato 5 — 2FA yo'q (muhim hisoblar)

Sababi: faqat parol 2.6-bob. Yechimi: 2FA (Misol 4).

Xato 6 — Zaif tiklash token

Sababi: taxmin qilinadigan/muddatsiz 2.7-bob. Yechimi: kuchli + muddat + bir martalik (Misol 5).

Xato 7 — Xavfsiz emas JWT (alg:none, zaif secret, localStorage)

Sababi: algoritm tekshirilmagan, zaif secret, XSS'ga ochiq saqlash 2.8-bob. Yechimi: algoritm majburla + kuchli secret + qisqa exp + refresh rotation + httpOnly cookie (Misol 6).


7. Integratsiya — bu mavzu stack'ning qayerida uchraydi

  • Auth (13.9, 5.15): Auth.js/Passport — parol hash, sessiya.
  • NestJS/Passport 8.7-bob: passport-local (parol tekshir), passport-jwt (JWT strategiya), @nestjs/passport guard'lar — bu bobdagi qoidalar (bcrypt, algoritm majburlash, qisqa exp) shu yerda qo'llanadi.
  • Injection 14.3-bob: SQL/NoSQL — login chetlab o'tish.
  • CSRF 14.4-bob: sessiya/JWT cookie (SameSite), OAuth state.
  • Rate limiting 14.8-bob: brute force himoya.
  • Token 14.6-bob: JWT (alg:none, refresh rotation, storage), secrets — 2.8 chuqurroq.
  • OWASP 14.1-bob: A07 (Auth Failures).
  • Email 5.19-bob: parol tiklash havolasi.
  • Redis 5.21-bob: rate limit, sessiya, JWT qora ro'yxat.

8. Eng yaxshi amaliyotlar (best practices)

  • bcrypt/argon2 (sekin, salt — MD5/SHA emas — Misol 1).
  • Bir xil javob (enumeration oldini — 2.7).
  • Rate limit + lockout (brute force — Misol 2).
  • Uzunlik 12+ + buzilgan parol tekshir (NIST — Misol 3).
  • 2FA (TOTP/passkey — eng samarali — Misol 4).
  • Xavfsiz tiklash (kuchli token, muddat, bir martalik — Misol 5).
  • Sessiya — yangi ID (login), HttpOnly, logout bekor 2.7-bob.
  • Vaqt hujumi oldini (bir xil javob vaqti — Misol 1).
  • Default hisoblar yo'q (admin/admin — 2.7).
  • Parol URL/logda emas 2.7-bob.
  • JWT — algoritm majburla, qisqa exp, refresh rotation, httpOnly cookie (localStorage emas — Misol 6, 2.8).
  • OAuth/OIDC — state (CSRF), PKCE, redirect_uri validatsiya 2.8-bob.

9. Amaliy loyiha: "Xavfsiz Autentifikatsiya Tizimi"

To'liq xavfsiz auth tizimini mustahkamlash.

Maqsad

Auth tizimi qur — parol hash, brute force himoya, parol siyosati, 2FA, xavfsiz tiklash.

Talablar (requirements)

  1. Parol hash: bcrypt/argon2 (Misol 1).
  2. Bir xil javob: enumeration oldini (Misol 1).
  3. Brute force: rate limit + lockout (Misol 2).
  4. Parol siyosati: uzunlik + buzilgan parol tekshir (Misol 3).
  5. 2FA: TOTP (Misol 4).
  6. Xavfsiz tiklash: kuchli token + muddat + bir martalik (Misol 5).
  7. Sessiya: yangi ID (login), HttpOnly, logout bekor 2.7-bob.
  8. Test: brute force, enumeration, zaif parol sinab ko'r.
  9. Vaqt hujumi: bir xil javob vaqti (Misol 1).
  10. Audit: auth xatolari (default hisob, parol log) tekshir.

Maslahatlar (hint)

  • bcrypt (Xato 1).
  • Bir xil javob (Xato 2).
  • Rate limit (Xato 3).
  • 2FA (Xato 5).
  • Tiklash token (Xato 6).

"Tayyor" mezonlari (acceptance criteria)

  • bcrypt/argon2 hash.
  • Bir xil javob (enumeration yo'q).
  • Brute force himoya.
  • Parol siyosati + buzilgan tekshir.
  • 2FA (TOTP).
  • Xavfsiz tiklash.
  • JWT (agar ishlatilsa) — algoritm majburla + qisqa exp + refresh rotation.

Yechim kodi ataylab berilmagan — bu loyihani o'zingiz yozib ko'ring.


10. Xulosa va keyingi bobga ko'prik

Bu bobda autentifikatsiya va parol xavfsizligini chuqur o'rgandik:

  • Parol ochiq emas 2.1-bob; bcrypt/argon2 2.2-bob; salt/pepper 2.3-bob; parol siyosati (NIST — 2.4); brute force himoya 2.5-bob; 2FA 2.6-bob; sessiya/auth xatolari 2.7-bob; JWT xavfsizligi va OAuth/OIDC (alg:none, refresh rotation, storage, PKCE — 2.8).

Endi siz autentifikatsiyani xavfsiz qila olasiz: parol hash (bcrypt), brute force himoya, kuchli parol siyosati, 2FA, xavfsiz tiklash. Bu — OWASP A07 va har ilovaning poydevori.

Keyingi bob — 14.6-bob: Token va secrets xavfsizligi. Auth'ni bildik; endi token va maxfiy ma'lumot xavfsizligini ko'ramiz: JWT (tuzilishi, xavfsiz ishlatish, keng xatolar), access/refresh token strategiyasi, token saqlash (cookie vs localStorage — XSS/CSRF), secrets boshqaruvi (env, vault, kalit aylantirish), va API kalit xavfsizligi. Bu — zamonaviy auth va maxfiy ma'lumot himoyasi.


Foydalanilgan rasmiy/ishonchli manbalar

  • OWASP — "Authentication Cheat Sheet", "Password Storage Cheat Sheet", "Forgot Password Cheat Sheet", "Session Management Cheat Sheet"
  • OWASP — "JSON Web Token for Java Cheat Sheet" / JWT xavfsizlik tavsiyalari (alg:none, algoritm majburlash)
  • OWASP — A07:2021 "Identification and Authentication Failures"
  • NIST SP 800-63B — Digital Identity Guidelines (parol siyosati — uzunlik > murakkablik, buzilgan parol tekshir, davriy o'zgartirish tavsiya etilmasligi)
  • Argon2 — Password Hashing Competition (2015) g'olibi; OWASP Password Storage tavsiyalari (argon2id, bcrypt cost factor)
  • bcrypt / argon2 kutubxona hujjatlari; otplib (TOTP) hujjatlari
  • Have I Been Pwned — Pwned Passwords API (k-anonymity range so'rovi)
  • RFC 6238 (TOTP), RFC 7519 (JWT), RFC 6749 (OAuth 2.0), RFC 7636 (PKCE), OpenID Connect Core
  • W3C — Web Authentication (WebAuthn) / FIDO2 passkey spetsifikatsiyasi

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
14.5-bob: Autentifikatsiya va parol xavfsizligi — Wisar