flutter_auth_screen 0.1.5
flutter_auth_screen: ^0.1.5 copied to clipboard
Customizable PIN authentication plugin with biometric support, lockout protection, and pure UI components.
Flutter Auth Screen 🛡️ #
A modern, customizable, and production-ready Flutter plugin for PIN-based authentication with advanced security features.
✨ Features #
- 🎨 Fully Customizable UI - Complete control over colors, sizes, animations, and layout
- 🔐 PIN Strength Validation - Prevent weak PINs (sequential, repeating, common patterns)
- 👆 Biometric Authentication - Optional fingerprint/face ID support
- 🔒 Lockout Protection - Automatic lockout after failed attempts
- 🌙 Dark Theme Support - Built-in theme switching
- ♿ Accessibility - Full VoiceOver and semantic label support
- ⚡ Haptic Feedback - Customizable vibration patterns
- 🎭 Smooth Animations - Shake, scale, and fade effects
- 📦 Zero Business Logic - Pure UI components, you control storage and validation
- 🚀 Production Ready - Tested and optimized for real-world apps
📸 Screenshots #
| Set PIN | Verify PIN | Error State |
|---|---|---|
| [Set PIN] | [Verify PIN] | [Error] |
🚀 Getting Started #
Installation #
Add to your pubspec.yaml:
dependencies:
flutter_auth_screen: ^0.1.3
Run:
flutter pub get
Basic Usage #
1. Set PIN Screen
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SetPinScreen(
onPinSet: (pin) async {
// Save PIN to your preferred storage
await YourStorageService.savePin(pin);
return true; // Return true if successful
},
onCompleted: (success) {
if (success) {
Navigator.pop(context);
// Show success message
}
},
),
),
);
2. Verify PIN Screen
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => VerifyPinScreen(
onVerifyPin: (pin) async {
// Verify PIN against stored value
return await YourStorageService.verifyPin(pin);
},
onVerificationResult: (success, attemptsRemaining) {
if (success) {
Navigator.pop(context);
// Grant access
}
},
),
),
);
🎨 Customization #
Theme Customization #
SetPinScreen(
onPinSet: (pin) async => await savePin(pin),
config: PinScreenConfig(
// Colors
primaryColor: Colors.purple,
backgroundColor: Colors.white,
dotFilledColor: Colors.purple,
errorColor: Colors.red,
// Sizes
pinLength: 6,
dotSize: 20.0,
numberButtonSize: 80.0,
// Dark Theme
brightness: Brightness.dark,
// Animations
enableHaptic: true,
showShakeAnimation: true,
animationDuration: Duration(milliseconds: 300),
),
);
PIN Strength Validation #
SetPinScreen(
onPinSet: (pin) async => await savePin(pin),
config: PinScreenConfig(
// Prevent weak PINs
preventSequentialPins: true, // Blocks: 1234, 4321
preventRepeatingDigits: true, // Blocks: 1111, 2222
preventCommonPins: true, // Blocks: 0000, 1212, etc.
customBlockedPins: ['1234', '0000'], // Your custom blocked list
),
validatePin: (pin) {
// Optional: Add your own validation
if (pin.contains('13')) {
return 'PIN cannot contain 13';
}
return null;
},
);
Biometric Authentication #
VerifyPinScreen(
onVerifyPin: (pin) async => await verifyPin(pin),
config: PinScreenConfig(
showBiometric: true,
biometricIcon: Icons.fingerprint,
onBiometricAuth: () async {
// Implement biometric authentication
final authenticated = await LocalAuthentication().authenticate(
localizedReason: 'Authenticate to access',
);
return authenticated;
},
),
);
Forgot PIN Support #
VerifyPinScreen(
onVerifyPin: (pin) async => await verifyPin(pin),
config: PinScreenConfig(
showForgotPin: true,
forgotPinText: 'Forgot your PIN?',
onForgotPin: () {
// Navigate to password reset or recovery flow
Navigator.push(context, MaterialPageRoute(
builder: (context) => ForgotPinScreen(),
));
},
),
);
Lockout Protection #
VerifyPinScreen(
onVerifyPin: (pin) async => await verifyPin(pin),
maxAttempts: 5,
config: PinScreenConfig(
lockoutDuration: Duration(minutes: 5),
),
onVerificationResult: (success, attemptsRemaining) {
if (!success && attemptsRemaining == 0) {
// Handle lockout - save lockout time
YourStorageService.setLockoutUntil(
DateTime.now().add(Duration(minutes: 5)),
);
}
},
);
Custom Widgets #
PinScreenConfig(
// Custom header
headerWidget: Column(
children: [
Image.asset('assets/logo.png', height: 80),
SizedBox(height: 16),
Text('Secure Access', style: TextStyle(fontSize: 24)),
],
),
// Custom footer
footerWidget: Text(
'Your data is encrypted and secure',
style: TextStyle(fontSize: 12, color: Colors.grey),
),
// Custom number pad
customNumberPad: (context, onPressed, onDelete) {
return YourCustomNumberPad(
onPressed: onPressed,
onDelete: onDelete,
);
},
);
Accessibility #
PinScreenConfig(
enableVoiceOver: true,
pinDotSemanticLabel: 'PIN digit',
deleteButtonSemanticLabel: 'Delete last digit',
biometricButtonSemanticLabel: 'Use fingerprint authentication',
forgotPinSemanticLabel: 'Reset PIN',
);
🎯 Advanced Features #
Navigation Helpers #
For convenience, use built-in navigation helpers:
// Show Set PIN
final result = await FlutterAuthScreen.showSetPinDialog(
context: context,
onPinSet: (pin) async => await savePin(pin),
);
// Show Verify PIN
final verified = await FlutterAuthScreen.showVerifyPinDialog(
context: context,
onVerifyPin: (pin) async => await verifyPin(pin),
);
Complete Storage Example #
class PinService {
final _storage = SharedPreferences.getInstance();
Future<bool> savePin(String pin) async {
final prefs = await _storage;
final hashedPin = _hashPin(pin);
return await prefs.setString('user_pin', hashedPin);
}
Future<bool> verifyPin(String pin) async {
final prefs = await _storage;
final storedPin = prefs.getString('user_pin');
final hashedPin = _hashPin(pin);
return storedPin == hashedPin;
}
Future<bool> isPinSet() async {
final prefs = await _storage;
return prefs.containsKey('user_pin');
}
String _hashPin(String pin) {
// Use proper hashing in production (crypto package)
return pin; // Simplified for example
}
}
📚 Complete API Reference #
SetPinScreen #
| Parameter | Type | Description |
|---|---|---|
onPinSet |
Future<bool> Function(String) |
Called when PIN is set, return true if saved successfully |
onCompleted |
Function(bool)? |
Called after operation completes |
validatePin |
String? Function(String)? |
Custom validation, return error message or null |
onCancel |
VoidCallback? |
Called when user cancels |
primaryColor |
Color? |
Primary color override |
backgroundColor |
Color? |
Background color override |
config |
PinScreenConfig? |
Advanced configuration |
createTitle |
String |
Title for create step |
createSubtitle |
String |
Subtitle for create step |
confirmTitle |
String |
Title for confirm step |
confirmSubtitle |
String |
Subtitle for confirm step |
mismatchMessage |
String |
Message when PINs don't match |
VerifyPinScreen #
| Parameter | Type | Description |
|---|---|---|
onVerifyPin |
Future<bool> Function(String) |
Called to verify PIN, return true if correct |
onVerificationResult |
Function(bool, int)? |
Called after each attempt (success, remaining) |
onCancel |
VoidCallback? |
Called when user cancels |
canCancel |
bool |
Whether cancel button is shown |
maxAttempts |
int |
Maximum attempts before lockout (0 = unlimited) |
primaryColor |
Color? |
Primary color override |
backgroundColor |
Color? |
Background color override |
config |
PinScreenConfig? |
Advanced configuration |
title |
String |
Screen title |
subtitle |
String |
Screen subtitle |
incorrectPinMessage |
String Function(int)? |
Custom error message with remaining attempts |
maxAttemptsMessage |
String |
Message shown when max attempts reached |
PinScreenConfig #
See full configuration options in IMPLEMENTATION_GUIDE.md
🔐 Security Best Practices #
- Always hash PINs - Never store plain text PINs
- Use secure storage - Consider
flutter_secure_storagefor sensitive data - Implement lockout - Prevent brute force attacks with lockout periods
- Validate PIN strength - Use built-in validation to prevent weak PINs
- Add biometric option - Provide convenience without sacrificing security
- Encrypt stored data - Combine PIN with encryption for sensitive app data
🤝 Contributing #
Contributions are welcome! Please read CONTRIBUTING.md for details.
📄 License #
This project is licensed under the MIT License - see the LICENSE file for details.
💖 Support #
If you find this plugin helpful, please:
- ⭐ Star the repo
- 🐛 Report issues
- 📝 Suggest features
- 🔀 Submit PRs
📮 Contact #
- GitHub: Vaibhav Nayak
- Email: vaibhavnayakoctt@gmail.com
🙏 Acknowledgments #
Built with ❤️ for the Flutter community.
Made with Flutter 💙