DEV Community

Flutter Tanzania
Flutter Tanzania

Posted on

Biometric Authentication in Flutter(Face ID/ Fingerprint)

One of the essential thing in mobile application is security especially if your building a finance app, and one of the most used security measure is using biometric authentication, which means you verify user by using phone face ID, Fingerprint or phone password.

Authentication using biometrics can be challenging. As it requires a good understanding of the underlying platform's APIs and implementation details.

But also, not all devices support biometric authentication, which requires developers to handle when user device does not have biometric authentication.

Luck us flutter provides a package for this local_auth

This package implements biometric security with Face ID and Touch ID/Fingerprint.

😜 Let's dive in and learn how to implement it in our flutter app.

But wait we need to go through the following steps to implement this.

  • Setting up the project
  • Checking biometric availability
  • Requesting biometric authentication
  • Handling authentication results

Setting up the project

First thing we need to install local authentication to our project.

dependencies:
   local_auth: ^2.1.6
Enter fullscreen mode Exit fullscreen mode

Then run the following command to install this plugin, though if your using vsCode you do not need to run this.

flutter packages get
Enter fullscreen mode Exit fullscreen mode

Android Setup

Add following line under manifest tag in AndroidManifest.xml

<uses-permission android:name="android.permission.USE_BIOMETRIC"/>
Enter fullscreen mode Exit fullscreen mode

Then Update the MainActivity.kt file to use FlutterFragmentActivity instead of FlutterActivity:

//add this import
import io.flutter.embedding.android.FlutterFragmentActivity

//Chnage to FlutterFragmentActivity
class MainActivity: FlutterFragmentActivity() {
      // ...
}
Enter fullscreen mode Exit fullscreen mode

IOS Setup

Add following code to your info.plist

<key>NSFaceIDUsageDescription</key>
<string>Why is my app authenticating using face id?</string>
Enter fullscreen mode Exit fullscreen mode

😮‍💨 we're done with the setup now let's write some code.

Checking biometric availability

We need to make sure that user phone has biometric authentication before we request to use it.

To check if biometric authentication is available or not. We use canCheckBiometrics method on the LocalAuthentication class.

Create a statefull widget called LoginScreen and add the following functions

import 'package:local_auth/local_auth.dart';

final LocalAuthentication _localAuth = LocalAuthentication();

//Check if biometric auth is available
Future<boolean> hasBiometrics() async {
    try {
        return await _localAuth.canCheckBiometrics;
    } on PlatformException catch (e) {
        return false;
    }
}

//Check type of biometric auth available (Eg - Face ID, fingerprint)
Future<void> checkBiometricType() async {
  final availableBiometrics = await _localAuth.getAvailableBiometrics();
  print('Available biometrics: $availableBiometrics');
}
Enter fullscreen mode Exit fullscreen mode

hasBiometrics functions checks if user device has biometric authentication by using canCheckBiometrics

Authenticate user

If hasBiometrics function returns true now we can use biometric authentication to verify user.

Call the authenticate method of the LocalAuthentication class.

The authenticate method takes 3 parameters -

  • localizedReason - is the message to show to user while prompting them for authentication. This is typically along the lines of: 'Authenticate to access MyApp.'. This must not be empty.

  • authMessages - if you want to customize messages in the dialogs.

  • options - for configuring further authentication related options.

//Authenticate using biometric
  Future<bool> authenticate() async {
    final hasBiometric = await hasBiometrics();

    if (hasBiometric) {
      return await _localAuth.authenticate(
        localizedReason: "Scan fingerprint to authenticate",
        options: const AuthenticationOptions(
          //Shows error dialog for system-related issues
          useErrorDialogs: true,
          //If true, auth dialog is show when app open from background
          stickyAuth: true,
          //Prevent non-biometric auth like such as pin, passcode.
          biometricOnly: true,
        ),
      );
    } else {
      return false;
    }
  }
Enter fullscreen mode Exit fullscreen mode

Now let's build a simple UI for the authentication, we will have a login screen with a button and when a user is verified we will direct them to another page else we will display a snackbar of failure to authenticate.

Home screen

import 'package:flutter/material.dart';

class HomeScreen extends StatelessWidget {

    @override
    Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBar(title: const Text('Home Screen')),
            body: const Center(
                child: Text('Home Screen'),
            ),
        );
    }
}
Enter fullscreen mode Exit fullscreen mode

And in our LoginScreen return the following

Scaffold(
      appBar: AppBar(title: const Text('Login Screen')),
      body: Center(
        child: ElevatedButton(
          onPressed: () async {
            final isAuthenticated = await authenticate();

            if (isAuthenticated) {
              Navigator.push(
                context,
                MaterialPageRoute(builder: (_) => HomeScreen()),
              );
            } else {
              final snackBar = SnackBar(content: Text('Auth Failed'));
              ScaffoldMessenger.of(context).showSnackBar(snackBar);
            }
          },
          child: const Text('Authenticate'),
        ),
      ),
    );
Enter fullscreen mode Exit fullscreen mode

Now we are good to go, you can test this project in a real device to gain the experience.

Happy coding 🥳

Top comments (2)

Collapse
 
briton__ profile image
Briton JM

Nice one, I've to try this very soon in my project!

Collapse
 
fluttertanzania profile image
Flutter Tanzania

Happy coding, we're waiting for your feedback 🥳