Как сделать безопасный сброс пароля и восстановление аккаунта
Практика4 минРедакция Innovialabs
Коротко
Отправляйте случайный одноразовый токен с коротким сроком жизни и храните только его хеш, отвечайте одинаково независимо от наличия аккаунта, ограничивайте запросы, завершайте все сессии после сброса и не давайте восстановлению отключать 2FA.
Коротко
У безопасного сброса пароля пять свойств:
- Непредсказуемый токен из криптографически стойкого генератора.
- Короткий срок жизни и одноразовость: ссылка работает один раз и недолго.
- Нет перечисления пользователей: ответ одинаковый, есть такой email или нет.
- Лимиты на запрос ссылки и на попытки её использовать.
- Уборка после сброса: остальные сессии и токены отзываются, пользователь получает уведомление.
Восстановление аккаунта — это альтернативный способ войти. Если он слабее основного входа, атакующий пойдёт именно через него.
Шаг 1: генерация и хранение токена
Берите минимум 32 случайных байта из стойкого источника — не timestamp, не ID пользователя и не Math.random(). В базе храните только хеш токена, чтобы утечка базы не превращалась в набор рабочих ссылок.
import crypto from "node:crypto";
const token = crypto.randomBytes(32).toString("base64url");
const tokenHash = crypto.createHash("sha256").update(token).digest("hex");
// сохраняем: user_id, token_hash, expires_at, used_at = null
// открытый токен уходит только в ссылке в письме
Обычного SHA-256 здесь достаточно: токен длинный и случайный. Медленные хеши нужны для паролей, которые придумывают люди.
Шаг 2: срок жизни и одноразовость
- Ставьте короткий срок: минуты или час, а не дни.
- Помечайте токен использованным атомарно, чтобы два параллельных запроса не прошли оба:
UPDATE password_resets
SET used_at = now()
WHERE token_hash = $1 AND used_at IS NULL AND expires_at > now()
RETURNING user_id;
- При новом запросе сброса аннулируйте старые неиспользованные токены этого пользователя.
- На странице сброса задайте
Referrer-Policy: no-referrer, чтобы токен из URL не утёк в сторонние скрипты и аналитику.
Шаг 3: защита от перечисления пользователей
Форма «Забыли пароль» не должна показывать, какие email зарегистрированы:
- Всегда одно сообщение: «Если аккаунт с этим адресом существует, мы отправили инструкции».
- Время ответа должно быть похожим в обоих случаях — помогает отправка письма в фоновой задаче.
- Проверьте, что форма регистрации и ошибки входа не выдают ту же информацию другим путём.
Шаг 4: лимиты
Ограничивайте по email/аккаунту и по IP:
- запросы писем — чтобы никто не завалил почту пользователя и ваш почтовый бюджет;
- попытки ввода токена или SMS-кода — чтобы короткий код нельзя было перебрать;
- CAPTCHA или задержку включайте только при подозрительной активности, а не для всех.
Шаг 5: что происходит после сброса
- Хешируйте новый пароль функцией для паролей (Argon2id, bcrypt или scrypt).
- Завершите все сессии и refresh-токены, кроме, возможно, текущей. Если аккаунт был угнан, именно это выкидывает атакующего.
- Отзовите оставшиеся токены сброса.
- Отправьте уведомление: «Ваш пароль изменён. Если это были не вы, напишите в поддержку».
- Не логиньте пользователя автоматически, если включена 2FA, — сначала второй фактор.
Email или SMS
| Канал | Главные риски | Что делать |
|---|---|---|
| Ссылка в email | Взломанная почта, пересланная ссылка | Короткий срок, одноразовость, уведомление о смене |
| SMS-код | SIM swap, переназначение номера, перехват | Строгие лимиты попыток; не делать SMS единственным фактором для ценных аккаунтов |
| Поддержка | Социальная инженерия | Письменный регламент проверки, никаких исключений «потому что срочно» |
Смена email или телефона для восстановления — сама по себе чувствительное действие: требуйте текущий пароль или 2FA и уведомляйте старый адрес.
Восстановление и 2FA
Сброс пароля не должен отключать 2FA. Иначе доступ к почте даёт полный доступ к аккаунту. Обычная схема:
- сброс меняет только пароль, вход по-прежнему требует второй фактор;
- если второй фактор потерян — резервные коды, выданные при настройке 2FA;
- без резервных кодов — медленная ручная процедура: проверка личности, период ожидания и уведомления на все известные контакты перед отключением 2FA.
Частые ошибки
- Токены без срока жизни или многоразовые.
- Токены в открытом виде рядом с записью пользователя.
- Разные сообщения для «email не найден» и «письмо отправлено».
- Старые сессии живут после смены пароля.
- Секретные вопросы вроде «девичья фамилия матери» — ответы часто публичны или угадываются.