Flutter Liveness Detection Randomized Plugin
A Flutter plugin for liveness detection with randomized challenge response method with an interaction mechanism between the user and the system in the form of a movement challenge that indicates life is detected on the face. This plugin helps implement secure biometric authentication by detecting real human presence through dynamic facial verification challenges.
Author
Crafted with love by Bagus Subagja โค๏ธ
Feel free to fork and modify this package to suit your needs - that's much more enjoyable than stealing or claiming my code ๐
Preview ๐ช
https://github.com/user-attachments/assets/f7266dc9-c4a2-4fba-8684-0ead2f678180
Update 1.1.0
- โฑ๏ธ Added automatic cooldown feature after 3 failed verification attempts
- ๐ 10-minute waiting period with persistent countdown (survives app restarts)
- ๐ฏ Countdown only decreases when app is active (pauses when app is backgrounded)
- ๐ API Refactor: All parameters consolidated into
LivenessDetectionConfig - ๐ฏ Simplified API - only requires
contextandconfigparameters - ๐ ๏ธ Fixed customizedLabel logic for proper skip challenge behavior
- โ
Added validation:
customizedLabelmust not be null whenuseCustomizedLabelis true
Update 1.0.6
Face stretching already fixed on this version
Features โจ
- ๐ฑ Real-time face detection
- ๐ฒ Randomized challenge sequence generation
- ๐ซ Cross-platform support (iOS & Android)
- ๐จ Light and dark mode support
- โ High accuracy liveness verification
- ๐ Simple integration API
- ๐ญ Customizable liveness challenge labels
- โณ Flexible security verification duration
- ๐ฒ Adjustable number of liveness challenges
- ๐ ๏ธ Adjustable image quality result
- โฑ๏ธ Automatic cooldown after failed attempts
Getting Started ๐
Add this to your package's pubspec.yaml file:
dependencies:
flutter_liveness_detection_randomized_plugin: ^1.1.0
Usage ๐
final String? response = await FlutterLivenessDetectionRandomizedPlugin.instance.livenessDetection(
context: context,
config: LivenessDetectionConfig(
// Camera & Image Settings
cameraResolution: ResolutionPreset.medium, // Camera resolution
imageQuality: 100, // Image quality (0-100)
isEnableMaxBrightness: true, // Auto brightness adjustment
// Detection Settings
durationLivenessVerify: 60, // Detection timeout in seconds
showDurationUiText: false, // Show countdown timer
startWithInfoScreen: true, // Show tutorial screen
// UI Settings
isDarkMode: false, // Dark/light theme
showCurrentStep: true, // Show step counter
isEnableSnackBar: true, // Show result notifications
shuffleListWithSmileLast: true, // Randomize challenges with smile last
// Customization
useCustomizedLabel: false, // Enable custom labels
customizedLabel: LivenessDetectionLabelModel(
blink: '', // Empty string = skip challenge
lookDown: '', // Skip this challenge
lookLeft: null, // null = use default "Look LEFT"
lookRight: 'Turn Right', // Custom label
lookUp: 'Look Up Please', // Custom label
smile: null, // null = use default "Smile"
),
// Security Features
enableCooldownOnFailure: true, // Enable cooldown after failures
maxFailedAttempts: 3, // Failed attempts before cooldown
cooldownMinutes: 10, // Cooldown duration
),
);
Configuration Parameters ๐
Camera & Image Settings
cameraResolution: Camera quality (ResolutionPreset.low/medium/high)imageQuality: Output image quality 0-100 (default: 100)isEnableMaxBrightness: Auto brightness adjustment (default: true)
Detection Settings
durationLivenessVerify: Detection timeout in seconds (default: 45)showDurationUiText: Show countdown timer (default: false)startWithInfoScreen: Show tutorial before detection (default: false)
UI Settings
isDarkMode: Dark theme mode (default: true)showCurrentStep: Show current step number (default: false)isEnableSnackBar: Show success/failure notifications (default: true)shuffleListWithSmileLast: Randomize challenges with smile at end (default: true)
Customization
useCustomizedLabel: Enable custom challenge labels (default: false)customizedLabel: Custom labels for each challenge type
Security Features
enableCooldownOnFailure: Enable cooldown after failed attempts (default: true)maxFailedAttempts: Number of failures before cooldown (default: 3)cooldownMinutes: Cooldown duration in minutes (default: 10)
Cooldown Feature
The plugin includes an automatic cooldown mechanism to prevent brute force attempts:
- Configurable number of failed attempts before cooldown
- Configurable cooldown duration
- Countdown timer only decreases when app is active
- Cooldown state persists through app restarts
- Users see a countdown screen during cooldown period
Customized Steps Label
You can customize challenge labels or skip certain challenges:
- Use empty string
''to skip a challenge - Use
nullto keep default label - Provide custom string for personalized labels
- When
useCustomizedLabel: true,customizedLabelmust not be null
Complete Example ๐ก
import 'package:flutter_liveness_detection_randomized_plugin/index.dart';
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: ElevatedButton(
onPressed: () async {
final result = await FlutterLivenessDetectionRandomizedPlugin.instance.livenessDetection(
context: context,
config: LivenessDetectionConfig(
startWithInfoScreen: true,
isDarkMode: false,
showCurrentStep: true,
isEnableSnackBar: true,
),
);
if (result != null) {
// Liveness detection successful
print('Face captured: $result');
} else {
// Detection failed or cancelled
print('Detection failed');
}
},
child: Text('Start Liveness Detection'),
),
),
),
);
}
}
Platform Setup
Android
Add camera permission to your android/app/src/main/AndroidManifest.xml:
<uses-permission android:name="android.permission.CAMERA"/>
Minimum SDK version: 23
iOS
Add camera usage description to ios/Runner/Info.plist:
<key>NSCameraUsageDescription</key>
<string>Camera access is required for liveness detection</string>
Testing Scenarios ๐งช
The example app includes 8 comprehensive liveness scenarios to test all features:
Scenario 1: Default Configuration
LivenessDetectionConfig(
shuffleListWithSmileLast: true,
startWithInfoScreen: true,
// Standard settings
)
Scenario 2: Random Shuffle
LivenessDetectionConfig(
shuffleListWithSmileLast: false,
durationLivenessVerify: 30,
startWithInfoScreen: false,
)
Scenario 3: Dark Mode + High Resolution
LivenessDetectionConfig(
isDarkMode: true,
cameraResolution: ResolutionPreset.high,
durationLivenessVerify: 60,
)
Scenario 4: Custom Indonesian Labels
LivenessDetectionConfig(
useCustomizedLabel: true,
customizedLabel: LivenessDetectionLabelModel(
blink: 'Kedip 2-3 Kali',
lookUp: 'Lihat ke Atas',
smile: 'Tersenyum Lebar',
),
)
Scenario 5: Skip Steps (Minimal Challenges)
LivenessDetectionConfig(
useCustomizedLabel: true,
customizedLabel: LivenessDetectionLabelModel(
blink: 'Blink Eyes',
lookDown: '', // Skip
lookLeft: '', // Skip
lookRight: '', // Skip
lookUp: 'Look Up Please',
smile: 'Smile Wide',
),
)
Scenario 6: Timer + Cooldown Features
LivenessDetectionConfig(
showDurationUiText: true,
enableCooldownOnFailure: true,
maxFailedAttempts: 2,
cooldownMinutes: 5,
)
Scenario 7: Minimal Features
LivenessDetectionConfig(
isEnableMaxBrightness: false,
isEnableSnackBar: false,
showCurrentStep: false,
)
Scenario 8: All Features Enabled
LivenessDetectionConfig(
isDarkMode: true,
cameraResolution: ResolutionPreset.high,
showDurationUiText: true,
enableCooldownOnFailure: true,
useCustomizedLabel: true,
customizedLabel: LivenessDetectionLabelModel(
blink: '๐๏ธ Kedipkan Mata',
smile: '๐ Senyum Manis',
),
)
Migration Guide ๐
From v1.0.x to v1.1.0+
All parameters are now consolidated into the LivenessDetectionConfig object:
Before:
await plugin.livenessDetection(
context: context,
config: LivenessDetectionConfig(...),
isEnableSnackBar: true,
shuffleListWithSmileLast: true,
showCurrentStep: true,
isDarkMode: false,
);
After:
await plugin.livenessDetection(
context: context,
config: LivenessDetectionConfig(
isEnableSnackBar: true,
shuffleListWithSmileLast: true,
showCurrentStep: true,
isDarkMode: false,
// ... other parameters
),
);