Backend

Passkeys/WebAuthn на backend без паролей

Passkeys/WebAuthn на backend без паролей

Пароли — это самый слабый узел в системе безопасности любого приложения. Они крадутся через фишинг, подбираются брутфорсом или утекают из баз данных в открытом виде (или в виде слабых хешей). Индустрия пыталась решить это через 2FA/MFA, но это лишь добавило трения для пользователя.

Passkeys (на базе стандарта WebAuthn) предлагают радикальный подход: заменить общий секрет (пароль), который знают и клиент, и сервер, на пару ключей: приватный, который никогда не покидает устройство пользователя, и публичный, который хранится у нас в базе.

Что такое WebAuthn и Passkeys на самом деле?

Если отбросить маркетинговую шелуху, WebAuthn (Web Authentication API) — это стандарт взаимодействия браузера с аутентификатором (TouchID, FaceID, Windows Hello или USB-ключ типа YubiKey).

Passkeys — это эволюция этого стандарта. Главное отличие в том, что теперь приватный ключ может синхронизироваться между устройствами пользователя через облако (iCloud Keychain, Google Password Manager), что решает главную проблему ранних USB-ключей: «что делать, если я потерял флешку?».

С точки зрения бэкенда, мы больше не проверяем соответствие строки password её хешу в БД. Мы проверяем цифровую подпись, пришедшую от клиента, используя сохраненный публичный ключ.

Архитектура процесса: Как это работает «под капотом»

Весь процесс делится на два основных этапа: Регистрация и Аутентификация.

1. Регистрация (Создание Passkey)

Процесс регистрации — это своего рода «рукопожатие», в ходе которого сервер и клиент договариваются о доверии.

  1. Запрос на создание (Challenge): Сервер генерирует случайную строку (challenge), ID пользователя и параметры алгоритмов, которые он поддерживает. Эти данные отправляются на фронтенд.
  2. Генерация ключа на клиенте: Браузер вызывает API WebAuthn. Устройство пользователя просит биометрию (отпечаток или лицо). После подтверждения устройство генерирует пару ключей (приватный/публичный) специально для вашего домена.

Отправка ответа: Клиент отправляет серверу:

    • Публичный ключ.
    • ID созданного ключа (Credential ID).
    • Подписанный challenge.
    • Данные об аутентификаторе (attestation).

Валидация и сохранение: Бэкенд проверяет подпись с помощью полученного публичного ключа. Если всё верно, мы сохраняем Credential ID и Public Key в базе данных, привязав их к аккаунту пользователя.

2. Аутентификация (Вход в систему)

Когда пользователь возвращается, нам не нужно спрашивать пароль.

  1. Вызов аутентификации: Сервер отправляет новый случайный challenge и список доступных Credential ID для этого пользователя (или просит пользователя указать свой email).
  2. Подпись на устройстве: Браузер находит нужный приватный ключ, пользователь подтверждает личность биометрией, и устройство подписывает challenge.
  3. Проверка на бэкенде: Сервер достает из базы публичный ключ, соответствующий присланному Credential ID, и проверяет подпись. Если подпись валидна — сессия открыта.

Технические нюансы реализации на Backend

Реализовать WebAuthn «с нуля», вручную парся бинарные данные (CBOR), — это путь к созданию дыр в безопасности. Настоятельно рекомендую использовать проверенные библиотеки (например, fido2-lib для Node.js, python-fido2 для Python или аналоги для Go/Java).

Что важно хранить в базе данных?

Ваша таблица учетных данных должна измениться. Вместо одного поля password_hash, вам понадобится таблица user_credentials со следующими полями:

  1. user_id: Ссылка на пользователя.
  2. credential_id: Уникальный идентификатор ключа (обычно Base64 или бинарный вид).
  3. public_key: Сам публичный ключ (в формате COSE).
  4. sign_count: Счетчик подписей. Это критически важно для защиты от клонирования ключей. Если пришедший счетчик меньше или равен тому, что в базе, значит, ключ был скопирован.
  5. transports: Способ передачи (USB, BLE, NFC, Internal), чтобы подсказывать пользователю, как подключиться.

Безопасность и «подводные камни»

При реализации бэкенда обратите внимание на следующие моменты:

    • Валидация Domain (RP ID): WebAuthn жестко привязан к домену (Relying Party ID). Если вы зарегистрировали ключ на app.example.com, вы не сможете использовать его на other.example.com без специальной настройки. Это на корню убивает фишинг: поддельный сайт просто не сможет вызвать приватный ключ для вашего домена.
    • Challenge Entropy: Challenge должен быть криптографически стойким случайным числом и иметь короткий срок жизни (TTL). Никогда не используйте предсказуемые значения.
    • Обработка ошибок: Биометрия может сработать не с первого раза, или пользователь может отменить запрос. Бэкенд должен корректно обрабатывать такие сценарии, не разрывая сессию регистрации.

Сравнение: Пароли vs Passkeys (Таблица для бизнеса)

Критерий Пароли + 2FA Passkeys (WebAuthn)
UX (Пользовательский опыт) Ввод строки $\rightarrow$ Код из SMS/App Один клик $\rightarrow$ FaceID/TouchID
Безопасность Уязвимы к фишингу и утечкам БД Устойчивы к фишингу, в БД нет секретов
Стоимость владения Расходы на SMS-шлюзы, сброс паролей Бесплатно (используются ресурсы устройства)
Сложность внедрения Низкая (стандарт индустрии) Средняя/Высокая (нужна новая логика бэкенда)

Стратегия миграции: Как перейти на беспарольный режим?

Вы не можете просто «выключить» пароли завтра, иначе вы потеряете часть аудитории со старыми устройствами. Рекомендуемый путь внедрения:

  1. Опциональный второй фактор: Сначала внедрите WebAuthn как альтернативу SMS/OTP для двухфакторной аутентификации.
  2. Предложение «упростить вход»: После того как пользователь залогинился по паролю, предложите ему: «Хотите входить быстрее? Создайте ключ доступа (Passkey)».
  3. Постепенный отказ: Когда большая часть активных пользователей создаст Passkeys, сделайте их основным методом входа, оставив пароли как «запасной вариант» (recovery method).

Заключение

Переход на Passkeys — это не просто следование тренду, а решение фундаментальной проблемы безопасности. С точки зрения бэкенда, мы переходим от модели «хранения секретов» к модели «верификации доказательств».

Да, это требует переработки схемы базы данных и внедрения новых API, но профит в виде отсутствия утечек паролей и колоссального улучшения конверсии в логин полностью оправдывает эти затраты. Будущее за беспарольным миром, и сейчас — лучшее время, чтобы интегрировать WebAuthn в ваш стек.