better_local_auth 0.0.4
better_local_auth: ^0.0.4 copied to clipboard
Enhanced local authentication plugin for biometrics with required cryptoObject support for Android security compliance.
better_local_auth #
Enhanced Flutter plugin for local authentication with required cryptoObject support for Android security compliance.
Overview #
better_local_auth is a fork and enhancement of the local_auth-3.0.1 Flutter package. It addresses security concerns identified by static analysis tools like Ostorlab by making the Android cryptoObject parameter required for biometric authentication. This change ensures that apps using biometric authentication on Android are not flagged as insecure.
Key Features #
- Security First: Requires
cryptoObjecton Android to prevent security warnings from static analysis tools - Simplified Maintenance: Consolidates multiple packages into one, removes unused platform support
- Backward Compatibility: Maintains API compatibility with
local_auth-3.0.1where possible - Enhanced Features: Adds optional keychain support for iOS secure storage
- Clear Migration Path: Provides comprehensive migration guidance for developers
Platform Support #
| Platform | Supported | Changes from local_auth |
|---|---|---|
| Android | ✅ Yes | cryptoObject required |
| iOS | ✅ Yes | keychainOptions required |
| Windows | ❌ No | Removed |
| Web | ❌ No | Removed |
| Linux | ❌ No | Removed |
| macOS | ❌ No | Removed |
Installation #
Add better_local_auth to your pubspec.yaml:
dependencies:
better_local_auth: ^1.0.0
iOS Setup #
For iOS, you need to add the NSFaceIDUsageDescription key to your app's Info.plist file to use Face ID:
<key>NSFaceIDUsageDescription</key>
<string>Your reason for using Face ID (e.g., "App needs to authenticate using faces.")</string>
This description will be shown to users when they are asked for Face ID permission.
Usage #
Basic Authentication #
import 'package:better_local_auth/better_local_auth.dart';
import 'package:better_local_auth/src/types/types.dart';
final auth = LocalAuthentication();
// Create required cryptoObject and keychainOptions
final cryptoObject = CryptoObject.forSignature(
keyAlias: 'my_app_key',
data: Uint8List.fromList('data_to_sign'.codeUnits),
);
final keychainOptions = KeychainOptions(
serviceName: 'com.example.app',
accountName: 'user_token',
);
try {
final bool didAuthenticate = await auth.authenticate(
localizedReason: 'Please authenticate to access secure data',
cryptoObject: cryptoObject,
keychainOptions: keychainOptions,
);
if (didAuthenticate) {
// User authenticated successfully
}
} on ArgumentError catch (e) {
// Handle missing cryptoObject or keychainOptions
print('Security requirement missing: ${e.message}');
} on LocalAuthException catch (e) {
// Handle authentication errors
print('Authentication failed: ${e.code}');
}
Enhanced API #
For additional features, use BetterLocalAuthentication:
import 'package:better_local_auth/better_local_auth.dart';
final betterAuth = BetterLocalAuthentication();
// Use factory methods for common crypto objects
final signatureCrypto = BetterLocalAuthentication.createSignatureCryptoObject(
keyAlias: 'signing_key',
dataToSign: Uint8List.fromList('important_data'.codeUnits),
);
// Enhanced authentication with detailed results
final result = await betterAuth.authenticateEnhanced(
localizedReason: 'Authenticate to sign transaction',
cryptoObject: signatureCrypto,
keychainOptions: KeychainOptions(
serviceName: 'com.example.app',
accountName: 'transaction_signing',
),
);
if (result.authenticated) {
print('Authentication successful');
print('Crypto result: ${result.cryptoResult}');
print('Keychain key: ${result.keychainStorageKey}');
}
Device Capabilities #
final LocalAuthentication auth = LocalAuthentication();
// Check if device supports biometrics
final bool canAuthenticateWithBiometrics = await auth.canCheckBiometrics;
// Check if device supports any authentication
final bool canAuthenticate = await auth.isDeviceSupported();
// Get enrolled biometrics
final List<BiometricType> availableBiometrics = await auth.getAvailableBiometrics();
Migration from local_auth #
Breaking Changes #
- Android
cryptoObjectRequirement: ThecryptoObjectparameter is now required for Android authentication - iOS
keychainOptionsRequirement: ThekeychainOptionsparameter is now required for iOS authentication - Platform Support: Windows, Web, Linux, and macOS platforms are no longer supported
Migration Steps #
- Update Dependencies: Replace
local_authwithbetter_local_authin yourpubspec.yaml - Add Required Parameters: Update all
authenticate()calls to includecryptoObjectandkeychainOptions - Remove Platform-Specific Code: Remove any code specific to Windows, Web, Linux, or macOS
- Test on Both Platforms: Verify authentication works correctly on Android and iOS
Migration Example #
Before (local_auth):
import 'package:local_auth/local_auth.dart';
final auth = LocalAuthentication();
final bool didAuthenticate = await auth.authenticate(
localizedReason: 'Please authenticate',
);
After (better_local_auth):
import 'package:better_local_auth/better_local_auth.dart';
import 'package:better_local_auth/src/types/types.dart';
final auth = LocalAuthentication();
// Create required security objects
final cryptoObject = CryptoObject.forSignature(
keyAlias: 'my_app_key',
data: Uint8List.fromList('auth_data'.codeUnits),
);
final keychainOptions = KeychainOptions(
serviceName: 'com.example.app',
accountName: 'authentication',
);
final bool didAuthenticate = await auth.authenticate(
localizedReason: 'Please authenticate',
cryptoObject: cryptoObject,
keychainOptions: keychainOptions,
);
Common Migration Issues #
- Missing cryptoObject on Android: Will throw
ArgumentErrorwith clear message - Missing keychainOptions on iOS: Will throw
ArgumentErrorwith clear message - Platform-specific code: Remove any conditional code for unsupported platforms
Security Considerations #
Android CryptoObject Requirement #
The cryptoObject requirement ensures that biometric authentication on Android performs cryptographic operations, which:
- Prevents security warnings from static analysis tools like Ostorlab
- Ensures authentication results can be cryptographically verified
- Provides secure key storage in Android's Keystore system
- Enables secure operations like data signing and encryption
iOS Keychain Integration #
The keychainOptions requirement ensures secure storage of authentication results in iOS Keychain, which:
- Provides hardware-backed secure storage
- Enables secure token storage and retrieval
- Supports biometric-protected keychain items
- Maintains security even if device is lost or stolen
API Reference #
LocalAuthentication Class #
Maintains API compatibility with local_auth-3.0.1 but requires additional security parameters.
Methods:
authenticate()- Authenticate user with biometrics (requires cryptoObject and keychainOptions)stopAuthentication()- Cancel in-progress authenticationcanCheckBiometrics- Check if device supports biometricsisDeviceSupported()- Check if device supports any authenticationgetAvailableBiometrics()- Get list of enrolled biometrics
BetterLocalAuthentication Class #
Enhanced API with additional features and factory methods.
Methods:
createSignatureCryptoObject()- Factory method for signature crypto objectscreateCipherCryptoObject()- Factory method for encryption/decryption crypto objectsauthenticateEnhanced()- Enhanced authentication with detailed results
Data Models #
CryptoObject- Abstract class for cryptographic operationsKeychainOptions- Options for iOS keychain integrationAuthenticationOptions- Extended options including security parametersAuthResult- Enhanced authentication result with crypto and keychain data
Troubleshooting #
Common Issues #
-
ArgumentError: cryptoObject is required
- Solution: Create and provide a
CryptoObjectusing factory methods
- Solution: Create and provide a
-
ArgumentError: keychainOptions is required
- Solution: Create and provide
KeychainOptionswith service and account names
- Solution: Create and provide
-
Platform not supported
- Solution: Remove code for Windows, Web, Linux, or macOS platforms
-
Biometric hardware not available
- Solution: Check device capabilities before attempting authentication
Debugging Tips #
- Enable debug logging in development
- Check device biometric enrollment status
- Verify keychain permissions on iOS
- Test with different cryptoObject configurations
Contributing #
Contributions are welcome! Please see the CONTRIBUTING.md file for details.
License #
This project is licensed under the BSD 3-Clause License - see the LICENSE file for details.
Acknowledgments #
- Based on the original
local_authpackage from the Flutter team - Security improvements inspired by static analysis tool findings
- Community feedback and testing