patterntypescriptreact-nativeModerate
Biometric Authentication with expo-local-authentication
Viewed 0 times
biometricsFace IDTouch IDfingerprintexpo-local-authenticationexpo-secure-storeKeychain
Error Messages
Problem
Implementing biometric authentication (Face ID, Touch ID, fingerprint) correctly requires checking hardware availability, enrolled biometrics, and fallback to passcode.
Solution
Use
expo-local-authentication. Check hasHardwareAsync() and isEnrolledAsync() before attempting. Call authenticateAsync with disableDeviceFallback: false to allow passcode fallback. Store sensitive data in the Keychain/Keystore (not AsyncStorage) — use expo-secure-store.Why
Biometric data never leaves the secure enclave (iOS) or TEE (Android). Your app only receives a success/failure result.
expo-secure-store encrypts values using keys backed by the secure enclave, so even device backups cannot expose them.Gotchas
- Face ID requires the
NSFaceIDUsageDescriptionkey inInfo.plist(handled by Expo config plugin) - Biometric authentication does not work on simulators — test on physical devices
- On Android, different OEMs implement biometric prompts differently; always test on real hardware
- Re-enrollment (new fingerprint added) invalidates previously created biometric keys — handle this gracefully
Code Snippets
Biometric auth with hardware and enrollment checks
import * as LocalAuthentication from 'expo-local-authentication';
async function authenticateUser(): Promise<boolean> {
const hasHardware = await LocalAuthentication.hasHardwareAsync();
const isEnrolled = await LocalAuthentication.isEnrolledAsync();
if (!hasHardware || !isEnrolled) {
// Fall back to PIN/password UI
return false;
}
const result = await LocalAuthentication.authenticateAsync({
promptMessage: 'Authenticate to continue',
disableDeviceFallback: false,
cancelLabel: 'Use PIN instead',
});
return result.success;
}Revisions (0)
No revisions yet.