Розробка авторизації по біометрії (розпізнавання обличчя) у 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 робочих днів. Тестування на реальних пристроях різних вендорів займає значну частину часу — емулятор тут майже безполезен.







