Implementing biometric authentication in flutter

raicodesokwe

Erick Murai

Posted on April 29, 2022

Implementing biometric authentication in flutter

With biometric authentication, we are able to verify users of our apps based on the biological characteristics of the users of our app. This can be done by checking if a user's fingerprint or face matches his/her fingerprint/face id in the phone. This method of authentication has gained popularity in the recent past especially with fintech apps that require a high level of security. They use it to verify that the user is indeed who they say they are. The uniqueness of our fingerprints and faces makes biometric authentication one of the most secure ways of verifying a user's identity.
We shall create a simple project with three screens, a login screen, a signup screen and a homepage.
The entire code for the project is available here
We shall use firebase for authentication and the Lottie package for some animations to spruce up our app. We shall then add these packages to our pubspec.yaml file at the root of our project folder.

dependencies:
  flutter:
    sdk: flutter
  firebase_auth:
  lottie:
Enter fullscreen mode Exit fullscreen mode

Now onto the main subject of discussion which is biometric authentication. For this, we shall need to use the flutter_secure_storage package that shall enable us store the login details which in our case shall be an email and password securely. This package uses the AES encryption standard that ensures the security of our data.
Next up, the local_auth package. We shall use this to access the local on-device authentication mechanisms for our users. On Android, this is the fingerprint biometric authentication method while on IOS, this is the touch code, Face ID or lock code authentication mechanism. We shall then add these to our pubspec.yaml file.

dependencies:
  flutter:
    sdk: flutter
  local_auth:
  flutter_secure_storage:
Enter fullscreen mode Exit fullscreen mode

Please note that for the local_auth package to work in IOS, we need to add a user defaults permission allowing the use of Face ID in our app. This shall be added in our info.plist file which is located in [project]/ios/Runner/info.plist

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

Additionally, for the package to work in android, we need to add this piece of code to our MainActivity.java page which is located in [project]/android/app/main/java/MainActivity.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"));
    }
}
Enter fullscreen mode Exit fullscreen mode

We also have to add the USE_FINGERPRINT and USE_BIOMETRIC permissions in our AndroidManifest.xml file which is located in [project]/android/app/src/main/AndroidManifest.xml.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.example.app">
  <uses-permission android:name="android.permission.USE_FINGERPRINT"/>
 <uses-permission android:name="android.permission.USE_BIOMETRIC"/>
<manifest>
Enter fullscreen mode Exit fullscreen mode

Additionally, we should set the minSdkVersion in[project]/android/app/build.gradle to >= 18 so as to enable flutter_secure_storage to work

android {
    ...

    defaultConfig {
        ...
        minSdkVersion 18
        ...
    }

}
Enter fullscreen mode Exit fullscreen mode

Firstly, we shall create a new user in our app with firebase auth in our signup screen

class AuthService{
 signUp(String email, String password, context) async {
    try {
      await FirebaseAuth.instance
          .createUserWithEmailAndPassword(email: email, password: password);
    } on FirebaseAuthException catch (e) {
      ScaffoldMessenger.of(context)
          .showSnackBar(SnackBar(content: Text(e.message.toString())));
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Next, we shall create our login page where the bulk of our biometric authentication logic shall be contained. We shall create localauth and storage variables that we shall use throughout the page.

final LocalAuthentication localAuth = LocalAuthentication();
final storage = const FlutterSecureStorage();
Enter fullscreen mode Exit fullscreen mode

We should now go ahead and check if the device supports biometric authentication or not.

final canCheck = await localAuth.canCheckBiometrics;
final deviceIsSupported = await localAuth.isDeviceSupported();
Enter fullscreen mode Exit fullscreen mode

Afterwards, we shall get the available biometrics on the device.

List<BiometricType> availableBiometrics =
    await auth.getAvailableBiometrics();

if (Platform.isIOS) {
    if (availableBiometrics.contains(BiometricType.face)) {
        // Face ID.
    } else if (availableBiometrics.contains(BiometricType.fingerprint)) {
        // Touch ID.
    }
}
Enter fullscreen mode Exit fullscreen mode

We shall use a boolean flag bool _useTouchId = false; that shall check whether the user has checked to use biometric authentication upon first login and if so, we shall write the values of the user's email and password to flutter_secure_storage for storage and later retrieval if we use biometric authentication.

  final authenticated = await localAuth.authenticate(
                localizedReason: 'Enable Face ID to sign in more easily',
                useErrorDialogs: true,
                stickyAuth: true);

            if (authenticated) {
              storage.write(key: 'email', value: email);
              storage.write(key: 'password', value: password);
              storage.write(key: 'usingBiometric', value: 'true');
            }
Enter fullscreen mode Exit fullscreen mode

In subsequent logins, if we intend to use biometric authentication, we shall go ahead and read the email and password values from flutter_secure_storage for authentication.

 final authenticated = await localAuth.authenticate(
                localizedReason: 'Enable Face ID to sign in more easily');

            if (authenticated) {
              String? userStoredEmail = await storage.read(
                key: 'email',
              );
              String? userStoredPassword = await storage.read(
                key: 'password',
              );
              AuthService()
                  .signIn(userStoredEmail!, userStoredPassword!, context);
            }
Enter fullscreen mode Exit fullscreen mode

And that's it !!! All that's remaining is for us to create a simple homescreen with a logout button.

import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';

import 'loginpage.dart';

class HomePage extends StatelessWidget {
   HomePage({Key? key}) : super(key: key);
final _auth=FirebaseAuth.instance;
Color greenColor = const Color(0xFF00AF19);
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body:  Center(
        child: Text('Home screen',style: TextStyle(color: greenColor,fontWeight: FontWeight.w700,fontSize: 35),),
      ),
      floatingActionButton: FloatingActionButton(
        backgroundColor: greenColor,
        onPressed: ()async {
          await _auth.signOut();
          Navigator.pushReplacement(
          context, MaterialPageRoute(builder: (context) => LoginPage()));
        },
        child:const  Icon(Icons.logout,),
      ),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

And voila!!! Our app has a reliable and safe biometric authentication system.
Here is the project's source code and here is a video demo of the end result
Thanks for reading until the end (long read, I know)*. Stay tuned for more flutter tips in future

💖 💪 🙅 🚩
raicodesokwe
Erick Murai

Posted on April 29, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related