Типы MFA факторов
VoxKey поддерживает 5 типов MFA факторов через единый API. У каждого фактора одинаковый интерфейс challenge/verify -- разница в том, как пользователь предоставляет верификацию.
Сравнение
| Фактор | API значение | Доставка | Действие пользователя | Лучше всего для |
|---|---|---|---|---|
| TOTP | totp | Нет (генерируется приложением) | Ввести 6-значный код из приложения-аутентификатора | Наиболее безопасный для повседневного использования |
email | Код отправлен на email | Ввести 6-значный код из письма | Пользователи без приложения-аутентификатора | |
| SMS | sms | Код отправлен по SMS | Ввести 6-значный код из SMS | Запасной вариант |
| WebAuthn | webauthn | Запрос браузера | Прикосновение к сенсору / биометрия / ключ безопасности | Наивысшая безопасность, лучший UX |
| Backup Code | backup_code | Нет (предварительно сгенерированы) | Ввести 8-символьный код | Экстренный доступ при недоступности основного фактора |
Rate limits и TTL
| Параметр | Значение |
|---|---|
| TTL challenge | 5 минут |
| Макс. попыток верификации на challenge | 5 |
| Rate limit создания challenge | 5 в минуту (на пользователя+клиент) |
| Rate limit верификации | 10 за 5 минут (на пользователя+IP) |
TOTP
Использует приложения-аутентификаторы (Google Authenticator, Authy, 1Password и др.).
- Без внешней доставки -- код генерируется на устройстве пользователя
- Challenge создаёт запись, но ничего не отправляет
- Коды действительны ~30 секунд с допуском ±1 окно для расхождения часов
- Самый надёжный: работает офлайн, нет зависимости от провайдеров email/SMS
// Ответ challenge
{ "challenge_type": "code" }
// Запрос верификации
{ "code": "123456" }
Email
Одноразовый код, отправленный на зарегистрированный email пользователя.
- Challenge отправляет 6-значный код через сервис уведомлений realm'а
- Хэш кода хранится в challenge (не в сессии)
- Создание нового email challenge инвалидирует предыдущий (семантика переотправки)
- Ответ включает замаскированный email-адрес
// Ответ challenge
{
"challenge_type": "code",
"delivery": {
"destination": "t***@example.com",
"sent": true
}
}
SMS
Одноразовый код, отправленный по SMS на зарегистрированный телефон пользователя.
- Тот же паттерн что у Email, но через SMS канал
- Создание нового SMS challenge инвалидирует предыдущий
- Ответ включает замаскированный номер телефона
// Ответ challenge
{
"challenge_type": "code",
"delivery": {
"destination": "+7***45",
"sent": true
}
}
WebAuthn / Passkey
Аппаратные ключи безопасности, сканеры отпечатков, Face ID, Windows Hello.
- Challenge генерирует
PublicKeyCredentialRequestOptionsдля WebAuthn API браузера userVerificationустановлен в"required"для критичных действий- Ответ включает полный объект options для
navigator.credentials.get() - Клиент отправляет assertion response обратно для верификации
// Ответ challenge
{
"challenge_type": "webauthn",
"webauthn_options": {
"challenge": "base64url...",
"allowCredentials": [...],
"userVerification": "required"
}
}
// Запрос верификации
{
"credential": {
"id": "base64url...",
"rawId": "base64url...",
"response": {
"authenticatorData": "base64url...",
"clientDataJSON": "base64url...",
"signature": "base64url..."
},
"type": "public-key"
}
}
WebAuthn flow на клиенте
// 1. Получаем challenge
const { challenge_id, webauthn_options } = await createChallenge('webauthn');
// 2. WebAuthn API браузера
const credential = await navigator.credentials.get({
publicKey: webauthn_options,
});
// 3. Отправляем assertion на верификацию
const result = await fetch(`/api/v1/{realm}/mfa/challenges/${challenge_id}/verify`, {
method: 'POST',
headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ credential }),
});
Backup Codes
Предварительно сгенерированные одноразовые коды для экстренного доступа.
- 10 буквенно-цифровых кодов генерируются при регистрации
- Каждый код можно использовать только один раз -- потребляется сразу после успешной верификации
- Без внешней доставки -- пользователь должен заранее сохранить коды
- Используйте когда основной фактор недоступен (потерян телефон, нет доступа к email)
// Запрос верификации
{ "code": "A3BGP2ZW" }
warning
Backup коды одноразовые. После верификации код потребляется навсегда. Рекомендуется напоминать пользователям о перегенерации кодов когда их запас заканчивается.