Реалізація відновлення пароля на сайті: безпечний флоу
Проблема: типові помилки при реалізації відновлення пароля
Стандартний флоу Forgot Password здається простим: користувач вводить email, отримує посилання, задає новий пароль. Але на практиці розробники допускають помилки, які призводять до вразливостей: розкриття факту реєстрації, підбір токена, перебір rate limit. Ми налаштовуємо флоу на Laravel з використанням вбудованого Password Broker: токен генерується, хешується bcrypt і зберігається в таблиці password_resets з TTL 60 хвилин. Відповідь на запит відновлення однакова для існуючого та неіснуючого email — зловмисник не дізнається, чи зареєстрований користувач. OWASP рекомендує bcrypt для хешування токенів, і ми дотримуємося цієї практики.
Як працює флоу відновлення?
Користувач надсилає POST-запит на /forgot-password зі своїм email. Сервер створює токен, хешує його і зберігає в БД. Потім на email надсилається лист з посиланням виду https://example.com/reset-password?token=...&email=.... Користувач переходить за посиланням, бачить форму для нового пароля. Після надсилання POST /reset-password сервер верифікує токен (порівнює bcrypt-хеш), оновлює пароль і видаляє токен. Всі активні сесії користувача інвалідуються.
Які вразливості приховує стандартна реалізація?
Зберігання токена в plaintext — реалізація відновлення пароля
Якщо токен зберігається у відкритому вигляді, при витоку БД зловмисник може відразу відновити пароль будь-якого користувача. Ми використовуємо bcrypt-хеш — навіть скомпрометована база не розкриє токени. bcrypt спеціально спроєктований для хешування паролів: він повільний і включає сіль. MD5 і SHA-1/2 дозволяють перебрати мільйони комбінацій за секунду, а bcrypt уповільнює перебір у 1000 разів, роблячи атаку непрактичною.
Відсутність rate limiting
Без обмеження кількості запитів зловмисник може закидати сервер запитами на скидання, викликаючи навантаження на поштовий сервер. Ми встановлюємо ліміт: не більше 3 запитів на годину з одного email або IP.
Однакова відповідь для існуючого та неіснуючого email
Багато хто повертає різні помилки ("email не знайдено" vs "лист відправлено"), що дозволяє атакуючому перебрати базу email. Наше рішення завжди відповідає однаково: "Якщо email зареєстровано, лист відправлено".
Чому bcrypt, а не MD5/SHA?
bcrypt спеціально спроєктований для хешування паролів: він повільний і включає сіль. MD5 і SHA-1/2 — швидкі хеші, які дозволяють зловмиснику перебрати мільйони комбінацій за секунду. Bcrypt же уповільнює перебір у 1000 разів і більше, роблячи атаку непрактичною. Це означає, що наш підхід з bcrypt у 1000 разів безпечніший за зберігання токена у відкритому вигляді.
Як ми реалізуємо відновлення пароля під ключ
Ми використовуємо Laravel Password Broker, який надає готові методи для генерації, перевірки та видалення токенів. Приклад контролера:
use IlluminateSupportFacadesPassword; class ForgotPasswordController extends Controller { public function __invoke(Request $request) { $request->validate(['email' => 'required|email']); $status = Password::sendResetLink($request->only('email')); return $status === Password::RESET_LINK_SENT ? back()->with(['status' => __($status)]) : back()->withErrors(['email' => __($status)]); } } Для скидання пароля використовуємо Password::reset().
Зберігання токенів: таблиця password_resets з полями email, token (bcrypt), created_at. Токен живе 60 хвилин, після чого видаляється через cron або garbage collection. Приклад таблиці:
| token (bcrypt) | created_at | |
|---|---|---|
| [email protected] | [bcrypt hash] | — |
| [email protected] | [bcrypt hash] | — |
Завдяки bcrypt навіть при витоку БД токени не розшифрувати — це в 1000 разів безпечніше plaintext.
Типові помилки при реалізації
- Зберігання токена в plaintext
- Відсутність rate limiting
- Різні відповіді для існуючих/неіснуючих email
- Відсутність інвалідації сесій після зміни пароля
- Занадто довгий TTL токена (більше 1 години)
Порівняння підходів для надійності
| Підхід | Безпека | Складність |
|---|---|---|
| bcrypt-хеш токена (наш) | Висока | Низька |
| plaintext токен | Низька | Дуже низька |
| JWT токен з коротким TTL | Середня | Середня |
Наш підхід — оптимальний баланс безпеки та простоти підтримки. JWT з коротким TTL вимагає додаткової інфраструктури і не захищає від витоку токена, якщо секретний ключ скомпрометовано. Сертифіковані інженери гарантують якість реалізації.
Процес роботи
- Аналіз поточної системи аутентифікації та виявлення ризиків.
- Проєктування флоу: endpoints, валідація, rate limiting.
- Реалізація контролерів, міграції, кастомного шаблону листа.
- Тестування: unit-тести на скидання та відновлення, інтеграційні тести на rate limiting.
- Деплой та моніторинг.
Строки та що входить
Зазвичай реалізація займає 1–2 робочих дні. Входить:
- Кастомний контролер і маршрути
- Міграція для таблиці password_resets
- Кастомний шаблон листа (HTML+текст)
- Rate limiting (3 запити/год на email)
- Інвалідація сесій при зміні пароля
- Тести та документація
Ми маємо багаторічний досвід і виконали понад 30 проєктів з аутентифікації. Отримайте консультацію — оцінимо ваш проєкт безкоштовно. Замовте впровадження безпечного відновлення пароля під ключ — зв'яжіться з нами.







