Разработка авторизации по биометрии (распознавание лица) в Android-приложении
Биометрическое распознавание лица на Android — это не Face ID. У Apple — инфракрасная проекция 30 000 точек, аппаратный Secure Enclave, гарантированный класс защиты. У Android — разброс от инфракрасного сенсора на Pixel 8 до простой фронтальной камеры на бюджетных устройствах. И именно этот разброс создаёт большинство проблем при разработке.
Классы биометрии и почему это важно
Android разделяет биометрию на три класса защищённости:
- Class 1 (Convenience) — слабая: фронтальная камера без инфракрасного сенсора, как правило распознавание по 2D-фото. Не подходит для финансовых операций.
- Class 2 (Weak) — средняя: немного лучше, но всё ещё без гарантии Secure Enclave.
- Class 3 (Strong) — аппаратная гарантия, результат верифицируется TEE (Trusted Execution Environment) или Secure Element.
Вызов BiometricManager.canAuthenticate(BIOMETRIC_STRONG) вернёт BIOMETRIC_ERROR_NONE_ENROLLED или BIOMETRIC_ERROR_NO_HARDWARE на устройствах, где лицо зарегистрировано как Class 1. Это значит: нельзя просто попросить "биометрию лица" — надо явно проверять класс и принимать решение.
Для банковских и финтех-приложений принимаем только BIOMETRIC_STRONG. Для остальных — можно BIOMETRIC_WEAK с предупреждением пользователя.
Реализация через BiometricPrompt
API идентичен fingerprint-аутентификации — тот же BiometricPrompt, тот же CryptoObject. Разница в том, что BiometricManager.canAuthenticate() вернёт корректный класс для лица, и система сама выберет, что показывать пользователю — промпт для отпечатка или для лица.
Важная тонкость: на некоторых устройствах (Honor, некоторые версии MIUI) система показывает промпт лица и отпечатка одновременно. Это штатное поведение — система предлагает первый доступный метод.
val biometricManager = BiometricManager.from(context)
val canAuthenticate = biometricManager.canAuthenticate(
BiometricManager.Authenticators.BIOMETRIC_STRONG
)
when (canAuthenticate) {
BiometricManager.BIOMETRIC_SUCCESS -> launchBiometricPrompt()
BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE -> showFallback()
BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE -> showTemporaryError()
BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED -> promptEnrollment()
}
promptEnrollment() — открываем системные настройки биометрии через Intent(Settings.ACTION_BIOMETRIC_ENROLL) с extras EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED = BIOMETRIC_STRONG.
Жизненный цикл промпта и Fragment back stack
BiometricPrompt привязан к FragmentActivity. Если пользователь нажимает "назад" во время показа промпта — вызывается onAuthenticationError с кодом ERROR_USER_CANCELED. Но если Activity пересоздаётся (поворот экрана) во время открытого промпта — промпт исчезает без callback. Решение: отслеживать флаг isAuthenticating в ViewModel и перезапускать промпт при onResume, если флаг активен.
Фрагментация устройств: что проверяем вручную
| Производитель | Особенность |
|---|---|
| Samsung (One UI 5+) | Face ID класс Strong на флагманах, Weak на бюджетных |
| Xiaomi / MIUI 14 | canAuthenticate может вернуть неверный класс — нужна дополнительная проверка |
| Pixel 6+ | Полноценный Strong через сенсор под экраном или фронтальный IR |
| Huawei (HMS) | Собственный FaceManager API при отсутствии GMS |
Huawei без GMS — отдельная история. Там BiometricPrompt не работает. Подключаем com.huawei.hms:base и используем HuaweiBiometricManager через рефлексию или условную компиляцию под HMS flavor.
Безопасность: спуфинг-атаки
Распознавание лица по 2D-фото уязвимо к атаке фотографией. Google Play Protect не блокирует приложения с Class 1 биометрией, но финансовые регуляторы (PCI DSS, требования ЦБ) явно запрещают использовать её для авторизации платежей. Мы никогда не используем Class 1 для операций с деньгами или чувствительными данными.
Если клиент настаивает на поддержке старых бюджетных устройств — предлагаем двухфакторную схему: face (Class 1) + PIN. Это формально удовлетворяет требованиям 2FA без компрометации безопасности.
Этапы работы и сроки
Аудит целевого парка устройств → определение минимального класса биометрии → реализация KeyStore + CryptoObject flow → обработка HMS-сценария (если нужно) → тестирование на физических устройствах разных производителей → документирование ограничений по моделям.
Срок: 5–10 рабочих дней. Тестирование на реальных устройствах разных вендоров занимает значительную часть времени — эмулятор здесь почти бесполезен.







