← Назад к вопросам

Спроектировать процесс авторизации через SMS-код

1.0 Junior🔥 151 комментариев
#Требования и их анализ

Условие

Необходимо спроектировать процесс авторизации пользователя в мобильном банке через SMS-код.

Контекст:

  • Пользователь вводит номер телефона
  • Система отправляет SMS с кодом
  • Пользователь вводит код
  • При успешной проверке пользователь авторизуется

Задача:

  1. Нарисуйте Sequence Diagram для этого процесса
  2. Укажите все системы-участники: мобильное приложение, бэкенд, SMS-шлюз
  3. Опишите обработку ошибок: неверный код, истёк срок кода, превышен лимит попыток
  4. Какие нефункциональные требования нужно учесть?
  5. Как защититься от брутфорса?

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Решение: Проектирование процесса авторизации через SMS-код

Sequence Diagram

User (Мобильное приложение) -> Backend: 1. POST /auth/send-sms {phone: "+79991234567"}
Backend -> SMS-шлюз: 2. Отправить SMS с кодом
SMS-шлюз -> SMS-шлюз: 3. Генерирует код (6 цифр), сохраняет в очередь
SMS-шлюз -> SMS Provider: 4. Отправляет SMS на оператора
SMS Provider -> User: 5. SMS доставлена на телефон
User -> Backend: 6. POST /auth/verify-sms {phone, code}
Backend -> Backend: 7. Проверяет код (валиден ли, не истёк ли, лимит попыток)
Backend -> Database: 8. Создаёт сессию пользователя / JWT токен
Backend -> User: 9. Возвращает токен доступа (access_token, refresh_token)
User -> Backend: 10. Дальнейшие запросы с Authorization: Bearer {token}

Системы-участники

  1. Мобильное приложение (iOS/Android)

    • Интерфейс для ввода номера телефона
    • Интерфейс для ввода SMS-кода
    • Сохранение токенов в secure storage
  2. Бэкенд (API сервер)

    • Генерация и отправка SMS кодов
    • Верификация кодов
    • Управление сессиями
    • Выдача JWT токенов
  3. SMS-шлюз

    • Очередь сообщений (Redis/RabbitMQ)
    • Логирование и retry-логика
    • Отслеживание статуса доставки
  4. SMS Provider (Twilio, AWS SNS, Yandex.SMS)

    • Интеграция с операторами мобильной связи
    • Отправка SMS
    • Отчёты о доставке
  5. База данных

    • Таблица auth_codes (phone, code, created_at, expires_at, used, attempts)
    • Таблица users (id, phone, created_at, last_login_at)
    • Таблица sessions (user_id, token, refresh_token, expires_at)

Обработка ошибок

1. Неверный код

Сценарий: Пользователь вводит неправильный код

Бэкенд:
1. Проверяет, существует ли запись в auth_codes для данного номера
2. Сравнивает введённый код с сохранённым
3. Если не совпадают:
   - Инкрементирует счётчик попыток (attempts++)
   - Проверяет, не превышен ли лимит (max 5 попыток)
   - Возвращает HTTP 400: "Неверный код"
   
Ответ клиенту:
{
  "error": "invalid_code",
  "message": "Неверный код. Осталось 4 попытки",
  "attempts_remaining": 4
}

2. Истёк срок кода

Сценарий: Пользователь вводит код позже, чем через 10 минут

Бэкенд:
1. Получает запись из auth_codes
2. Проверяет: now() > expires_at (обычно TTL = 10 минут)
3. Если истёк:
   - Удаляет запись (или помечает как expired)
   - Возвращает HTTP 400 с ошибкой
   
Ответ клиенту:
{
  "error": "code_expired",
  "message": "Код истёк. Запросите новый код.",
  "retry_after_seconds": 60
}

3. Превышен лимит попыток

Сценарий: Пользователь ввёл неверный код 5+ раз (брутфорс)

Бэкенд:
1. При каждой неудачной попытке проверяет attempts >= 5
2. Если превышен лимит:
   - Блокирует номер на время (например, 30 минут)
   - Удаляет или делает невалидным текущий код
   - Возвращает HTTP 429 Too Many Requests
   
Ответ клиенту:
{
  "error": "too_many_attempts",
  "message": "Слишком много неудачных попыток. Попробуйте позже.",
  "retry_after_seconds": 1800,
  "blocked_until": "2024-03-23T15:35:00Z"
}

4. Номер телефона не найден при отправке

Сценарий: Пользователь вводит номер, которого нет в системе

Бэкенд:
1. Может быть два подхода:
   
   Подход А (Security-friendly):
   - Создаёт нового пользователя при первом входе
   - Отправляет SMS код
   - После верификации создаёт аккаунт
   
   Подход Б (Старые системы):
   - Проверяет в БД, есть ли пользователь с таким номером
   - Если нет: возвращает HTTP 404 или HTTP 400
   - Предлагает пройти регистрацию

Мой рекомендация: Подход А (более удобен для пользователя)

5. SMS не доставлена (провайдер недоступен)

Сценарий: Ошибка при отправке SMS на стороне провайдера

Бэкенд:
1. Пытается отправить SMS через primary провайдера (Twilio)
2. Если ошибка (timeout, 503):
   - Добавляет задачу в очередь retry (с exponential backoff)
   - Возвращает пользователю: "SMS отправляется. Обычно приходит за 30 сек"
   - Логирует ошибку для мониторинга
3. Retry стратегия:
   - 1-я попытка: сразу
   - 2-я: через 5 сек
   - 3-я: через 30 сек
   - 4-я: через 2 минуты
   - После 4-й неудачи: уведомляет пользователя о проблеме

Нефункциональные требования

1. Безопасность

  • Шифрование при передаче: TLS 1.3 для всех запросов
  • Хранение кодов: Пароли не нужны, но коды должны быть захешированы (bcrypt)
  • Rate limiting: 5 попыток отправки SMS на номер в 5 минут (защита от spam)
  • Шифрование логов: SMS коды не должны храниться в plaintext логах

2. Производительность

  • Время отправки SMS: < 100ms на стороне API (асинхронно)
  • Время верификации: < 50ms (query в БД + проверка)
  • Доступность SMS-шлюза: 99.5%

3. Надёжность

  • Retry логика: Exponential backoff для SMS отправки
  • Idempotency: Если пользователь дважды отправит запрос на отправку SMS, не создаём дублирующиеся коды
  • Timeout: API запросы к SMS провайдеру должны иметь таймаут 5 сек, затем fallback

4. Масштабируемость

  • Async SMS отправка: Отправка SMS должна быть асинхронной (через очередь, не blocking request)
  • Caching: Кэшировать информацию о пользователях в Redis (чтобы не бить БД на каждый запрос)
  • Database: Таблица auth_codes должна быть оптимизирована:
    • Индекс по (phone, created_at)
    • Удаление старых записей (TTL) через cleanup job

5. Соответствие регуляциям

  • GDPR: Удалять SMS коды через 30 дней
  • Логирование: Вести аудит всех попыток верификации (для расследования мошенничества)
  • Локализация: SMS должна быть на языке пользователя

Защита от брутфорса

1. Rate limiting на уровне номера телефона

- Максимум 5 попыток верификации за 15 минут
- Максимум 10 запросов на отправку нового кода за 1 час
- При превышении: блокируем номер на 30 минут

2. Rate limiting на уровне IP-адреса

- Максимум 50 запросов на отправку SMS за 1 час
- Максимум 100 попыток верификации за 1 час
- При превышении: блокируем IP на 1 час

3. CAPTCHA для подозрительной активности

Если обнаруживаем:
- Множественные запросы с разных IP на один номер
- Множественные запросы на один IP на разные номера
- Паттерны: последовательные номера телефонов

То требуем пройти CAPTCHA перед отправкой SMS

4. Список чёрных номеров

Ведём базу номеров, которые:
- Были использованы для мошенничества
- Множественно пытались угадать коды
- Зарегистрировали более 10 аккаунтов за день

На такие номера не отправляем SMS

5. Мониторинг и алерты

Логируем и алертим в Slack если:
- Количество неудачных попыток > 100 в час
- Количество SMS отправок на один номер > 20 в час
- Количество SMS отправок с одного IP > 500 в час
- Обнаружены паттерны перебора номеров

Улучшения для production

  1. Backup каналы: Email, Telegram bot, push-уведомления
  2. Биометрия: После первого входа через SMS - предложить Face ID / Touch ID
  3. WebAuthn / FIDO2: Для ещё большей безопасности
  4. Device fingerprinting: Запоминать девайс пользователя, снизить требования при повторном входе с того же девайса
  5. Телеметрия: Отслеживать время доставки SMS, провайдеры с наибольшей задержкой, подключаться к альтернативным провайдерам
Спроектировать процесс авторизации через SMS-код | PrepBro