| # local_auth | 
 |  | 
 | This Flutter plugin provides means to perform local, on-device authentication of | 
 | the user. | 
 |  | 
 | This means referring to biometric authentication on iOS (Touch ID or lock code) | 
 | and the fingerprint APIs on Android (introduced in Android 6.0). | 
 |  | 
 | ## Usage in Dart | 
 |  | 
 | Import the relevant file: | 
 |  | 
 | ```dart | 
 | import 'package:local_auth/local_auth.dart'; | 
 | ``` | 
 |  | 
 | To check whether there is local authentication available on this device or not, call canCheckBiometrics: | 
 |  | 
 | ```dart | 
 | bool canCheckBiometrics = | 
 |     await localAuth.canCheckBiometrics; | 
 | ``` | 
 |  | 
 | Currently the following biometric types are implemented: | 
 |  | 
 | - BiometricType.face | 
 | - BiometricType.fingerprint | 
 |  | 
 | To get a list of enrolled biometrics, call getAvailableBiometrics: | 
 |  | 
 | ```dart | 
 | List<BiometricType> availableBiometrics = | 
 |     await auth.getAvailableBiometrics(); | 
 |  | 
 | if (Platform.isIOS) { | 
 |     if (availableBiometrics.contains(BiometricType.face)) { | 
 |         // Face ID. | 
 |     } else if (availableBiometrics.contains(BiometricType.fingerprint)) { | 
 |         // Touch ID. | 
 |     } | 
 | } | 
 | ``` | 
 |  | 
 | We have default dialogs with an 'OK' button to show authentication error | 
 | messages for the following 2 cases: | 
 |  | 
 | 1. Passcode/PIN/Pattern Not Set. The user has not yet configured a passcode on | 
 |    iOS or PIN/pattern on Android. | 
 | 2. Touch ID/Fingerprint Not Enrolled. The user has not enrolled any | 
 |    fingerprints on the device. | 
 |  | 
 | Which means, if there's no fingerprint on the user's device, a dialog with | 
 | instructions will pop up to let the user set up fingerprint. If the user clicks | 
 | 'OK' button, it will return 'false'. | 
 |  | 
 | Use the exported APIs to trigger local authentication with default dialogs: | 
 |  | 
 | The `authenticate()` method uses biometric authentication, but also allows | 
 | users to use pin, pattern, or passcode. | 
 |  | 
 | ```dart | 
 | var localAuth = LocalAuthentication(); | 
 | bool didAuthenticate = | 
 |     await localAuth.authenticate( | 
 |         localizedReason: 'Please authenticate to show account balance'); | 
 | ``` | 
 |  | 
 | To authenticate using biometric authentication only, set `biometricOnly` to `true`. | 
 |  | 
 | ```dart | 
 | var localAuth = LocalAuthentication(); | 
 | bool didAuthenticate = | 
 |     await localAuth.authenticate( | 
 |         localizedReason: 'Please authenticate to show account balance', | 
 |         biometricOnly: true); | 
 | ``` | 
 |  | 
 | If you don't want to use the default dialogs, call this API with | 
 | 'useErrorDialogs = false'. In this case, it will throw the error message back | 
 | and you need to handle them in your dart code: | 
 |  | 
 | ```dart | 
 | bool didAuthenticate = | 
 |     await localAuth.authenticate( | 
 |         localizedReason: 'Please authenticate to show account balance', | 
 |         useErrorDialogs: false); | 
 | ``` | 
 |  | 
 | You can use our default dialog messages, or you can use your own messages by | 
 | passing in IOSAuthMessages and AndroidAuthMessages: | 
 |  | 
 | ```dart | 
 | import 'package:local_auth/auth_strings.dart'; | 
 |  | 
 | const iosStrings = const IOSAuthMessages( | 
 |     cancelButton: 'cancel', | 
 |     goToSettingsButton: 'settings', | 
 |     goToSettingsDescription: 'Please set up your Touch ID.', | 
 |     lockOut: 'Please reenable your Touch ID'); | 
 | await localAuth.authenticate( | 
 |     localizedReason: 'Please authenticate to show account balance', | 
 |     useErrorDialogs: false, | 
 |     iOSAuthStrings: iosStrings); | 
 |  | 
 | ``` | 
 |  | 
 | If needed, you can manually stop authentication for android: | 
 |  | 
 | ```dart | 
 |  | 
 | void _cancelAuthentication() { | 
 |     localAuth.stopAuthentication(); | 
 | } | 
 |  | 
 | ``` | 
 |  | 
 | ### Exceptions | 
 |  | 
 | There are 6 types of exceptions: PasscodeNotSet, NotEnrolled, NotAvailable, OtherOperatingSystem, LockedOut and PermanentlyLockedOut. | 
 | They are wrapped in LocalAuthenticationError class. You can | 
 | catch the exception and handle them by different types. For example: | 
 |  | 
 | ```dart | 
 | import 'package:flutter/services.dart'; | 
 | import 'package:local_auth/error_codes.dart' as auth_error; | 
 |  | 
 | try { | 
 |   bool didAuthenticate = await local_auth.authenticate( | 
 |       localizedReason: 'Please authenticate to show account balance'); | 
 | } on PlatformException catch (e) { | 
 |   if (e.code == auth_error.notAvailable) { | 
 |     // Handle this exception here. | 
 |   } | 
 | } | 
 | ``` | 
 |  | 
 | ## iOS Integration | 
 |  | 
 | Note that this plugin works with both Touch ID and Face ID. However, to use the latter, | 
 | you need to also add: | 
 |  | 
 | ```xml | 
 | <key>NSFaceIDUsageDescription</key> | 
 | <string>Why is my app authenticating using face id?</string> | 
 | ``` | 
 |  | 
 | to your Info.plist file. Failure to do so results in a dialog that tells the user your | 
 | app has not been updated to use Face ID. | 
 |  | 
 | ## Android Integration | 
 |  | 
 | Note that local_auth plugin requires the use of a FragmentActivity as | 
 | opposed to Activity. This can be easily done by switching to use | 
 | `FlutterFragmentActivity` as opposed to `FlutterActivity` in your | 
 | manifest (or your own Activity class if you are extending the base class). | 
 |  | 
 | Update your MainActivity.java: | 
 |  | 
 | ```java | 
 | import android.os.Bundle; | 
 | import io.flutter.app.FlutterFragmentActivity; | 
 | import io.flutter.plugins.flutter_plugin_android_lifecycle.FlutterAndroidLifecyclePlugin; | 
 | import io.flutter.plugins.localauth.LocalAuthPlugin; | 
 |  | 
 | public class MainActivity extends FlutterFragmentActivity { | 
 |     @Override | 
 |     protected void onCreate(Bundle savedInstanceState) { | 
 |         super.onCreate(savedInstanceState); | 
 |         FlutterAndroidLifecyclePlugin.registerWith( | 
 |                 registrarFor( | 
 |                         "io.flutter.plugins.flutter_plugin_android_lifecycle.FlutterAndroidLifecyclePlugin")); | 
 |         LocalAuthPlugin.registerWith(registrarFor("io.flutter.plugins.localauth.LocalAuthPlugin")); | 
 |     } | 
 | } | 
 | ``` | 
 |  | 
 | OR | 
 |  | 
 | Update your MainActivity.kt: | 
 |  | 
 | ```kotlin | 
 | import io.flutter.embedding.android.FlutterFragmentActivity | 
 | import io.flutter.embedding.engine.FlutterEngine | 
 | import io.flutter.plugins.GeneratedPluginRegistrant | 
 |  | 
 | class MainActivity: FlutterFragmentActivity() { | 
 |     override fun configureFlutterEngine(flutterEngine: FlutterEngine) { | 
 |         GeneratedPluginRegistrant.registerWith(flutterEngine) | 
 |     } | 
 | } | 
 | ``` | 
 |  | 
 | Update your project's `AndroidManifest.xml` file to include the | 
 | `USE_FINGERPRINT` permissions: | 
 |  | 
 | ```xml | 
 | <manifest xmlns:android="http://schemas.android.com/apk/res/android" | 
 |           package="com.example.app"> | 
 |   <uses-permission android:name="android.permission.USE_FINGERPRINT"/> | 
 | <manifest> | 
 | ``` | 
 |  | 
 | On Android, you can check only for existence of fingerprint hardware prior | 
 | to API 29 (Android Q). Therefore, if you would like to support other biometrics | 
 | types (such as face scanning) and you want to support SDKs lower than Q, | 
 | _do not_ call `getAvailableBiometrics`. Simply call `authenticate` with `biometricOnly: true`. | 
 | This will return an error if there was no hardware available. | 
 |  | 
 | ## Sticky Auth | 
 |  | 
 | You can set the `stickyAuth` option on the plugin to true so that plugin does not | 
 | return failure if the app is put to background by the system. This might happen | 
 | if the user receives a phone call before they get a chance to authenticate. With | 
 | `stickyAuth` set to false, this would result in plugin returning failure result | 
 | to the Dart app. If set to true, the plugin will retry authenticating when the | 
 | app resumes. | 
 |  | 
 | ## Getting Started | 
 |  | 
 | For help getting started with Flutter, view our online | 
 | [documentation](https://flutter.dev/). | 
 |  | 
 | For help on editing plugin code, view the [documentation](https://flutter.dev/docs/development/packages-and-plugins/developing-packages#plugin). |