Add biometric authentication as a login shortcut for returning users. Use the local_auth package in a Custom Action to check device biometric capabilities and authenticate with fingerprint or face ID. Store credentials securely using flutter_secure_storage after the initial email/password login. On subsequent app launches, prompt biometric verification and auto-login with stored credentials. Include a settings toggle to enable or disable biometric login and a PIN fallback after three failed biometric attempts.
Adding Biometric Login to Your FlutterFlow App
Biometric authentication lets returning users unlock your app with fingerprint or face recognition instead of typing their password every time. This tutorial implements biometric login as a convenience shortcut on top of standard email/password authentication. The initial login uses email/password, and biometric is offered as an optional fast unlock for subsequent sessions.
Prerequisites
- A FlutterFlow project with Firebase Authentication (email/password) configured
- The local_auth and flutter_secure_storage packages added as dependencies
- A physical device or emulator with biometric capabilities for testing
- Basic familiarity with FlutterFlow Custom Actions
Step-by-step guide
Check device biometric capabilities with a Custom Action
Check device biometric capabilities with a Custom Action
Create a Custom Action checkBiometricSupport that imports the local_auth package. Call LocalAuthentication().canCheckBiometrics and LocalAuthentication().isDeviceSupported() to verify the device has biometric hardware and at least one biometric enrolled. Return a boolean indicating support. Call this action on app startup and store the result in App State isBiometricAvailable. Use this value to conditionally show or hide biometric-related UI elements throughout the app.
1// Custom Action: checkBiometricSupport2import 'package:local_auth/local_auth.dart';34Future<bool> checkBiometricSupport() async {5 final auth = LocalAuthentication();6 try {7 final canCheck = await auth.canCheckBiometrics;8 final isSupported = await auth.isDeviceSupported();9 if (!canCheck || !isSupported) return false;10 final available = await auth.getAvailableBiometrics();11 return available.isNotEmpty;12 } catch (e) {13 return false;14 }15}Expected result: The app detects whether the device supports biometric authentication and stores the result in App State.
Store credentials securely after initial email/password login
Store credentials securely after initial email/password login
After a successful email/password login, if the user has enabled biometric login (App State isBiometricEnabled == true), create a Custom Action storeCredentials that uses flutter_secure_storage to save the email and a refresh token. The secure storage encrypts data using the device keychain (iOS) or KeyStore (Android). Never store the raw password; store the Firebase refresh token instead, which can be used to re-authenticate. Write: storage.write(key: 'user_email', value: email) and storage.write(key: 'refresh_token', value: token).
1// Custom Action: storeCredentials2import 'package:flutter_secure_storage/flutter_secure_storage.dart';34Future<void> storeCredentials(5 String email, String refreshToken) async {6 const storage = FlutterSecureStorage();7 await storage.write(key: 'user_email', value: email);8 await storage.write(key: 'refresh_token', value: refreshToken);9}Expected result: Login credentials are encrypted and stored in the device secure storage after the first successful login.
Build the biometric prompt screen and authentication flow
Build the biometric prompt screen and authentication flow
Create a BiometricPromptPage that appears on app launch when isBiometricEnabled is true. Display a fingerprint or face Icon (large, centered), a Text ('Verify your identity'), and a 'Use Password Instead' TextButton below. On Page Load, trigger a Custom Action authenticateBiometric that calls LocalAuthentication().authenticate(localizedReason: 'Verify your identity to access the app'). On success, read stored credentials from flutter_secure_storage, use the refresh token to re-authenticate with Firebase, and navigate to the home page. On failure, increment a failedAttempts Page State counter. After 3 failures, navigate to the standard login page.
1// Custom Action: authenticateBiometric2import 'package:local_auth/local_auth.dart';34Future<bool> authenticateBiometric() async {5 final auth = LocalAuthentication();6 try {7 return await auth.authenticate(8 localizedReason: 'Verify your identity to access the app',9 options: const AuthenticationOptions(10 stickyAuth: true,11 biometricOnly: false,12 ),13 );14 } catch (e) {15 return false;16 }17}Expected result: The device biometric prompt appears on app launch. Successful verification auto-logs in the user.
Add the biometric toggle in the settings page
Add the biometric toggle in the settings page
On your SettingsPage, add a Row with Text ('Biometric Login') and a Switch widget. Show this row with Conditional Visibility only when App State isBiometricAvailable is true. On Switch toggle ON: first authenticate with biometric to confirm the user owns the biometric, then set App State isBiometricEnabled to true and store current credentials using the storeCredentials Custom Action. On Switch toggle OFF: set isBiometricEnabled to false and delete stored credentials from flutter_secure_storage using storage.deleteAll(). Persist isBiometricEnabled in the user Firestore document so the setting survives app reinstalls.
Expected result: Users can enable or disable biometric login from settings, with the toggle only visible on supported devices.
Implement PIN fallback for failed biometric attempts
Implement PIN fallback for failed biometric attempts
Create a PINEntryPage as a fallback after 3 failed biometric attempts or when biometric hardware is temporarily unavailable. Use a Column with a Text ('Enter your PIN'), four Container boxes showing entered digits as dots, and a custom number pad Grid of Containers (1-9, 0, backspace, confirm). Store the PIN hash (not plain text) in flutter_secure_storage when the user first sets it up. On PIN entry, hash the input and compare with the stored hash. On match, read credentials from secure storage and auto-login. After 5 failed PIN attempts, require full email/password login and clear stored credentials.
Expected result: A PIN entry screen provides a secure fallback when biometric authentication fails.
Complete working example
1PACKAGES REQUIRED:2 local_auth: ^2.1.03 flutter_secure_storage: ^9.0.045APP STATE:6 isBiometricAvailable: Boolean (set on app start)7 isBiometricEnabled: Boolean (persisted, user preference)89APP LAUNCH FLOW:10 1. Custom Action: checkBiometricSupport()11 → Set App State isBiometricAvailable12 2. If isBiometricEnabled == true:13 → Navigate to BiometricPromptPage14 3. Else:15 → Navigate to standard LoginPage1617BIOMETRIC PROMPT PAGE:18 Column (centered)19 ├── Icon (fingerprint, size 80)20 ├── Text ("Verify your identity")21 ├── Text ("Use Password Instead", link)22 On Page Load:23 → authenticateBiometric()24 → If success: readCredentials() → autoLogin() → HomePage25 → If fail: increment failedAttempts26 → If failedAttempts >= 3: navigate to PINEntryPage2728SETTINGS PAGE:29 Row (Conditional: isBiometricAvailable)30 ├── Text ("Biometric Login")31 └── Switch32 On Toggle ON:33 1. authenticateBiometric() to confirm34 2. storeCredentials(email, refreshToken)35 3. Set isBiometricEnabled = true36 On Toggle OFF:37 1. clearCredentials()38 2. Set isBiometricEnabled = false3940PIN FALLBACK PAGE:41 Column42 ├── Text ("Enter your PIN")43 ├── Row (4 dot indicators)44 └── Grid (number pad 0-9 + backspace + confirm)45 On Confirm: hash(input) == stored hash46 → If match: autoLogin()47 → If 5 failures: navigate to LoginPage4849SECURITY RULES:50 - Never store plain-text passwords51 - Use device secure storage (keychain/keystore)52 - Hash PINs with SHA-25653 - Clear credentials on biometric disable54 - Require re-auth after 3 biometric failuresCommon mistakes when creating a Secure Login System with Biometric Authentication in FlutterFlow
Why it's a problem: Using biometric as the only authentication method without an initial login
How to avoid: Always require an initial email/password login first. Biometric serves as a convenience shortcut for subsequent sessions, not a replacement for primary authentication.
Why it's a problem: Storing the user password in plain text for auto-login after biometric
How to avoid: Store the Firebase refresh token instead of the password. Refresh tokens can be revoked server-side if compromised, limiting the damage.
Why it's a problem: Not providing a fallback when biometric fails
How to avoid: Implement a PIN fallback after 3 failed biometric attempts, and always show a 'Use Password Instead' option that navigates to the standard login page.
Best practices
- Use biometric as a login shortcut, not a replacement for primary email/password authentication
- Store refresh tokens in flutter_secure_storage, never plain-text passwords
- Check canCheckBiometrics and isDeviceSupported before showing biometric UI
- Provide a PIN fallback and a password fallback for when biometric fails
- Hash PINs with SHA-256 before storing, never compare or store plain-text PINs
- Clear all stored credentials when the user disables biometric login
- Require biometric verification when the user enables the feature to confirm device ownership
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I want to add biometric login (fingerprint and face ID) to my FlutterFlow app. Show me how to use the local_auth package in a Custom Action, store credentials securely with flutter_secure_storage, implement the biometric prompt flow on app launch, add a settings toggle, and create a PIN fallback for failed attempts.
Create a biometric login screen with a large fingerprint icon centered on the page, a verification message below it, and a text link to use password instead at the bottom.
Frequently asked questions
Does biometric authentication work on both iOS and Android?
Yes. The local_auth package supports Face ID and Touch ID on iOS, and fingerprint and face recognition on Android. The authenticate() method automatically uses whatever biometric is available on the device.
What happens if the user changes their biometric on the device?
When a user adds or removes a fingerprint/face on the device, the operating system invalidates existing biometric enrollments. Your app should handle the resulting authentication failure by falling back to PIN or password login.
Can I use biometric to authorize specific actions like payments?
Yes. Call authenticateBiometric() before any sensitive action (payment, password change, data export). The localizedReason parameter lets you customize the prompt message for each use case.
Is flutter_secure_storage truly secure?
Yes, it uses the iOS Keychain and Android KeyStore, which are hardware-backed encrypted storage. Data is encrypted at rest and tied to the device. It is the standard approach for storing sensitive data in Flutter apps.
What if the device does not have biometric hardware?
The checkBiometricSupport Custom Action detects this and sets isBiometricAvailable to false. The biometric toggle in settings will not appear, and the app uses standard email/password login exclusively.
Can RapidDev help implement advanced authentication systems?
Yes. RapidDev can build multi-factor authentication combining biometric, PIN, email verification, and SMS OTP for maximum security, along with session management and device trust policies.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation