Como implementar biometria e autenticação local em apps mobile
1. Introdução à autenticação local e biometria em dispositivos móveis
1.1. Conceitos fundamentais: o que é autenticação local e por que usá-la
Autenticação local é o processo de verificar a identidade do usuário diretamente no dispositivo, sem depender de servidores remotos. Ela utiliza recursos nativos do hardware — como sensores biométricos ou armazenamento seguro — para validar que a pessoa que está acessando o app é realmente o proprietário do dispositivo. A principal vantagem é a velocidade: o usuário não precisa digitar senhas longas ou esperar por conexão de rede. Além disso, a autenticação local reduz a superfície de ataque, já que as credenciais nunca saem do aparelho.
1.2. Diferença entre autenticação biométrica e métodos tradicionais
Métodos tradicionais (PIN, padrão, senha alfanumérica) dependem de algo que o usuário sabe. Eles são vulneráveis a ataques de observação (shoulder surfing) e podem ser esquecidos. Já a autenticação biométrica usa algo que o usuário é: impressão digital, mapa facial ou íris. No iOS, o Face ID cria um modelo matemático do rosto usando o sensor TrueDepth; no Android, o BiometricPrompt gerencia sensores de impressão digital (capacitivos, ópticos ou ultrassônicos) e reconhecimento facial. A biometria oferece melhor experiência do usuário, mas exige fallbacks para quando o sensor falha.
1.3. Cenários de uso comuns
- Desbloqueio de app: abrir um banco ou cofre digital sem digitar senha.
- Confirmação de pagamentos: autorizar transações no Apple Pay ou Google Pay.
- Acesso a dados sensíveis: exibir histórico médico ou documentos fiscais.
- Reautenticação em sessões longas: exigir nova verificação após 5 minutos de inatividade.
2. Plataformas suportadas e APIs nativas
2.1. Android: BiometricPrompt e Android Keystore
A partir da API nível 28 (Android 9), o BiometricPrompt unifica todos os métodos biométricos. Ele interage com o Android Keystore, que armazena chaves criptográficas em hardware isolado (TEE ou StrongBox). O fluxo básico:
1. Criar um BiometricPrompt com callback de sucesso/erro.
2. Configurar BiometricPrompt.PromptInfo com título, subtítulo e descrição.
3. Chamar biometricPrompt.authenticate().
2.2. iOS: LocalAuthentication e Secure Enclave
O framework LocalAuthentication fornece o LAContext, que verifica a presença de biometria cadastrada e executa a autenticação. O Secure Enclave é um coprocessador que gerencia chaves e nunca expõe os dados biométricos ao sistema operacional.
let context = LAContext()
var error: NSError?
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics,
localizedReason: "Desbloqueie o app") { success, error in
// tratar resultado
}
}
2.3. Limitações e fallbacks
- Biometria não disponível: dispositivo sem sensor ou com sensor danificado.
- Biometria não cadastrada: usuário não configurou impressão digital ou Face ID.
- Falha na leitura: dedo molhado, mudança facial (barba, óculos).
- Fallback obrigatório: oferecer PIN ou senha do dispositivo como alternativa.
3. Implementação prática com React Native (Expo e CLI)
3.1. Usando expo-local-authentication
O pacote expo-local-authentication abstrai as APIs nativas. Instale com:
expo install expo-local-authentication
3.2. Exemplo de código
import * as LocalAuthentication from 'expo-local-authentication';
async function authenticateWithBiometrics() {
// 1. Verificar disponibilidade
const hasHardware = await LocalAuthentication.hasHardwareAsync();
const isEnrolled = await LocalAuthentication.isEnrolledAsync();
if (!hasHardware || !isEnrolled) {
Alert.alert('Biometria não disponível');
return false;
}
// 2. Solicitar autenticação
const result = await LocalAuthentication.authenticateAsync({
promptMessage: 'Autentique-se para acessar o app',
fallbackLabel: 'Usar senha',
cancelLabel: 'Cancelar',
});
// 3. Tratar resultado
if (result.success) {
console.log('Autenticado com sucesso');
return true;
} else {
console.log('Falha na autenticação:', result.error);
return false;
}
}
3.3. Tratamento de erros
// Possíveis erros retornados por result.error:
// 'user_cancel' - usuário cancelou
// 'not_enrolled' - nenhuma biometria cadastrada
// 'not_available' - hardware ausente
// 'lockout' - muitas tentativas, aguardar 30s
4. Implementação prática com Flutter
4.1. Pacote local_auth
Adicione ao pubspec.yaml:
dependencies:
local_auth: ^2.1.0
Configure permissões no Android (AndroidManifest.xml):
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
No iOS, adicione ao Info.plist:
<key>NSFaceIDUsageDescription</key>
<string>Este app usa Face ID para autenticação segura</string>
4.2. Exemplo de código
import 'package:local_auth/local_auth.dart';
final LocalAuthentication auth = LocalAuthentication();
Future<bool> authenticate() async {
// 1. Verificar disponibilidade
final bool canAuthenticate = await auth.canCheckBiometrics || await auth.isDeviceSupported();
if (!canAuthenticate) return false;
// 2. Solicitar autenticação
try {
final bool authenticated = await auth.authenticate(
localizedReason: 'Autentique-se para continuar',
options: const AuthenticationOptions(
biometricOnly: true, // apenas biometria, sem PIN
stickyAuth: true, // mantém sessão ativa
),
);
return authenticated;
} catch (e) {
print('Erro: $e');
return false;
}
}
4.3. Gerenciamento de fallback
Future<bool> authenticateWithFallback() async {
bool authenticated = await authenticate();
if (!authenticated) {
// Fallback para PIN do dispositivo
authenticated = await auth.authenticate(
localizedReason: 'Use seu PIN ou padrão',
options: const AuthenticationOptions(
biometricOnly: false, // permite senha do dispositivo
),
);
}
return authenticated;
}
5. Armazenamento seguro de credenciais após autenticação
5.1. Keychain (iOS) e EncryptedSharedPreferences (Android)
Após a biometria, você pode liberar uma chave criptográfica que descriptografa dados armazenados. No iOS, o Keychain armazena tokens com proteção kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly. No Android, o EncryptedSharedPreferences usa AES-256 com chave derivada do Android Keystore.
5.2. Integração com React Native
// Instalar: npm install react-native-keychain
import * as Keychain from 'react-native-keychain';
async function saveToken(token: string) {
// A biometria protege o acesso ao Keychain
await Keychain.setGenericPassword('session_token', token, {
service: 'com.meuapp.token',
accessControl: Keychain.ACCESS_CONTROL.BIOMETRY_CURRENT_SET,
accessible: Keychain.ACCESSIBLE.WHEN_UNLOCKED_THIS_DEVICE_ONLY,
});
}
async function getToken() {
const credentials = await Keychain.getGenericPassword({
authenticationPrompt: { title: 'Autentique-se para recuperar o token' },
});
return credentials ? credentials.password : null;
}
5.3. Integração com Flutter
// Instalar: flutter pub add flutter_secure_storage
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
final storage = FlutterSecureStorage();
Future<void> saveSecureToken(String token) async {
await storage.write(
key: 'auth_token',
value: token,
aOptions: AndroidOptions(encryptedSharedPreferences: true),
iOptions: IOSOptions(
accessibility: KeychainAccessibility.first_unlock_this_device,
authenticationType: AuthenticationType.biometrics,
),
);
}
Future<String?> readSecureToken() async {
return await storage.read(
key: 'auth_token',
iOptions: IOSOptions(
authenticationType: AuthenticationType.biometrics,
),
);
}
6. Boas práticas de segurança e experiência do usuário
6.1. Nunca armazenar a biometria em si
A biometria nunca deve ser salva no seu app. Use-a apenas como gatilho para liberar chaves criptográficas armazenadas no Keystore/Secure Enclave. O sistema operacional gerencia os templates biométricos.
6.2. Feedback visual e sonoro
- No Android, o BiometricPrompt exibe animação nativa.
- No iOS, o Face ID mostra um ícone de rosto animado.
- Adicione feedback tátil (HapticFeedback) em apps customizados.
6.3. Política de timeout e reautenticação
Defina um tempo de sessão (ex: 5 minutos). Após esse período, exija nova autenticação biométrica. Use um timer no estado global do app:
// Exemplo conceitual
sessionTimer = Timer(Duration(minutes: 5), () {
setState(() { isSessionValid = false; });
});
7. Testes e depuração em diferentes dispositivos
7.1. Simulando biometria
- Android Emulator: AVD Manager → Configurações → Fingerprint → "Touch to simulate fingerprint".
- iOS Simulator: Hardware → Face ID → Enrolled. Use
xcrun simctl spawn bootedpara simular rosto válido/inválido.
7.2. Testes em dispositivos reais
- Sensores ultrassônicos (Samsung Galaxy S21): funcionam com dedo molhado.
- Sensores ópticos (muitos chineses): falham com luz solar direta.
- Face ID: testar com óculos escuros, máscara cirúrgica (iOS 15.4+).
7.3. Logs e monitoramento
Use ferramentas como Sentry ou Crashlytics para capturar falhas de autenticação. Registre o tipo de erro sem expor dados sensíveis:
// Log seguro
analytics.logEvent('biometric_failure', {
'error_code': result.error,
'device_model': DeviceInfo.getModel(),
});
8. Considerações finais e próximos passos
8.1. Comparação com autenticação por terceiros
- Apple ID / Google Sign-In: autenticação remota, útil para criar conta, mas não substitui a biometria local para reautenticação rápida.
- Combinação ideal: use biometria local para desbloqueio de sessão e Apple/Google para login inicial.
8.2. Tendências futuras
- Autenticação contínua: monitorar comportamento do usuário (digitação, marcha) para validar identidade durante toda a sessão.
- Autenticação passiva: usar sensores (Wi-Fi, Bluetooth) para detectar ambiente confiável.
8.3. Checklist de implementação para produção
- [ ] Fallback para PIN/senha do dispositivo.
- [ ] Tratamento de
lockout(muitas tentativas). - [ ] Armazenamento seguro de tokens com biometria.
- [ ] Timeout de sessão configurável.
- [ ] Testes em pelo menos 5 dispositivos reais diferentes.
- [ ] Logs de falhas sem expor dados biométricos.
Referências
- Documentação oficial do BiometricPrompt (Android) — Guia completo da Google sobre implementação de autenticação biométrica no Android, incluindo fallbacks e boas práticas.
- LocalAuthentication Framework - Apple Developer — Documentação oficial da Apple sobre o framework LocalAuthentication, com exemplos de Face ID e Touch ID.
- expo-local-authentication - Expo Documentation — Referência oficial do pacote Expo para autenticação biométrica, com exemplos de código e tratamento de erros.
- local_auth package - Flutter — Página oficial do pacote Flutter para autenticação local, com instruções de configuração e exemplos para Android e iOS.
- react-native-keychain - GitHub — Repositório oficial da biblioteca para armazenamento seguro de credenciais no Keychain (iOS) e Keystore (Android), com suporte a biometria.
- Secure storage best practices - OWASP Mobile Top 10 — Guia do OWASP sobre armazenamento seguro em dispositivos móveis, incluindo recomendações para uso de biometria e chaves criptográficas.
- Android Keystore System - Android Developers — Documentação técnica sobre o sistema Android Keystore, que gerencia chaves criptográficas protegidas por hardware biométrico.