Last active
April 11, 2024 12:06
-
-
Save CoderNamedHendrick/27e9272cf9a0c6f8cdede8ad4dbfaedb to your computer and use it in GitHub Desktop.
Clean Biometrics implementation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/services.dart'; | |
import 'package:local_auth/error_codes.dart' as auth_error; | |
import 'package:local_auth/local_auth.dart' as local_auth; | |
class BiometricsService implements BiometricsInterface { | |
const BiometricsService(); | |
static final _auth = local_auth.LocalAuthentication(); | |
@override | |
Future<EitherExceptionOr<bool>> authenticateBiometric() async { | |
try { | |
final bool didAuthenticate = await _auth.authenticate( | |
localizedReason: 'Please authenticate to enter #App Name', | |
options: const local_auth.AuthenticationOptions( | |
stickyAuth: true, | |
), | |
); | |
return Right(didAuthenticate); | |
} on PlatformException catch (e) { | |
if (e.code == auth_error.notAvailable || | |
e.code == auth_error.biometricOnlyNotSupported) { | |
return const Left( | |
ClientException(exceptionMessage: 'No Biometrics Available')); | |
} | |
if (e.code == auth_error.notEnrolled) { | |
return const Left(ClientException( | |
exceptionMessage: | |
'No Auth Available, please create biometric authentication then try again.')); | |
} | |
if (e.code == auth_error.passcodeNotSet) { | |
return const Left(ClientException( | |
exceptionMessage: | |
'Can\'t use biometrics, no passcode/pin set for device')); | |
} | |
if (e.code == auth_error.lockedOut) { | |
return const Left(ClientException( | |
exceptionMessage: | |
'Biometric auth locked due to too many attempts! Try again later')); | |
} | |
if (e.code == auth_error.permanentlyLockedOut) { | |
return const Left(ClientException( | |
exceptionMessage: | |
'Biometric auth locked dut to too many attempts! Use passcode/pin to unlock')); | |
} | |
return const Left( | |
ClientException(exceptionMessage: 'Something went wrong'), | |
); | |
} | |
} | |
@override | |
Future<BiometricType> getAvailableBiometricType() async { | |
final availableBiometrics = await _auth.getAvailableBiometrics(); | |
if (availableBiometrics.contains(local_auth.BiometricType.strong)) { | |
return _getBiometricTypeFromAvailable(availableBiometrics); | |
} | |
return _getBiometricTypeFromAvailable(availableBiometrics); | |
} | |
BiometricType _getBiometricTypeFromAvailable( | |
List<local_auth.BiometricType> availableBiometrics, | |
) { | |
if (Platform.isIOS) { | |
if (availableBiometrics.contains(local_auth.BiometricType.face)) { | |
return BiometricType.faceId; | |
} | |
return BiometricType.fingerprint; | |
} | |
return BiometricType.fingerprint; | |
} | |
@override | |
Future<bool> isBiometricAvailable() async { | |
final canCheckBiometrics = await _auth.canCheckBiometrics; | |
final availableBiometrics = await _auth.getAvailableBiometrics(); | |
return canCheckBiometrics && availableBiometrics.isNotEmpty; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
enum BiometricType { fingerprint, faceId } | |
abstract interface class BiometricsInterface { | |
Future<bool> isBiometricAvailable(); | |
Future<BiometricType> getAvailableBiometricType(); | |
Future<EitherExceptionOr<bool>> authenticateBiometric(); | |
} | |
final biometricsServiceProvider = | |
Provider.autoDispose<BiometricsInterface>((ref) { | |
return const BiometricsService(); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment