Безопасный сброс пароля за 6 шагов
Процесс сброса пароля должен быть безопасным и надежным. Вот как это сделать правильно:
Шаги безопасного сброса пароля
-
Прием электронной почты
- Всегда возвращайте одинаковый ответ HTTP 200 независимо от того, существует ли указанный адрес электронной почты.
-
Генерация токена
- Создайте случайный токен длиной 32 байта и сохраните его хэшированную версию в базе данных.
-
Хранение токена
- Сохраняйте только хэшированный токен с ограничением времени жизни (например, 15 минут) и флагом одноразового использования.
-
Отправка токена пользователю
- Отправьте необработанный токен пользователю через электронную почту или другой защищенный канал связи.
-
Проверка токена при отправке формы
- При получении запроса на смену пароля проверьте соответствие полученного токена хранимому хешу.
-
Обновление состояния после успешного сброса
- После успешной смены пароля пометьте токен как использованный, обновите пароль пользователя и завершите все активные сессии.
Если хотя бы один из этих шагов отсутствует, ваш процесс сброса пароля будет уязвим.
Пример реализации схемы базы данных
import { bigserial, pgTable, text, timestamp } from "drizzle-orm/pg-core";
export const users = pgTable("users", {
id: bigserial("id", { mode: "number" }).primaryKey(),
email: text("email").notNull().unique(),
passwordHash: text("password_hash").notNull(),
});
export const passwordResetTokens = pgTable("password_reset_tokens", {
id: bigserial("id", { mode: "number" }).primaryKey(),
userId: bigserial("user_id", { mode: "number" }).notNull(),
tokenHash: text("token_hash").notNull(),
expiresAt: timestamp("expires_at").notNull(),
usedAt: timestamp("used_at"),
});
Обратите внимание на поле tokenHash. Если ваша база данных подвергнется утечке, злоумышленник не сможет использовать украденные данные для сброса паролей пользователей.