An Android Biometric Authentication Tutorial

From Techotopia
Revision as of 14:12, 20 July 2018 by Neil (Talk | contribs) (Created page with "Touch sensors are now built into many Android devices to identify the user and provide access to both the device and application functionality such as in-app payment options u...")

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Touch sensors are now built into many Android devices to identify the user and provide access to both the device and application functionality such as in-app payment options using fingerprint recognition. Fingerprint recognition is, of course, just one of a number of different authentication methods including passwords, PIN numbers and, more recently, facial recognition.

Although only a few Android devices currently on the market provide facial recognition, it is likely that this will become more common in the near future. In recognition of this, Google has begun to transition away from what was a fingerprint-centric approach to adding authentication to apps to a less specific approach that is referred to as biometric authentication. In the initial release of Android 8, these biometric features only cover fingerprint authentication but this will change in future releases and updates of the Android operating system and SDK.

This chapter provides both an overview of biometric authentication and a detailed, step by step tutorial that demonstrates a practical approach to implementing biometric authentication within an Android app project.


Contents


An Overview of Biometric Authentication

The key biometric authentication component is the BiometricPrompt class. This class performs much of the work that previously had to be performed by writing code in earlier Android versions, including displaying a standard dialog to guide the user through the authentication process, performing the authentication and reporting the results to the app. The class also handles excessive failed authentication attempts and enforces a timeout before the user can try again.

The BiometricPrompt class includes a companion Builder class that can be used to configure and create BiometricPrompt instances, including defining the text that is to appear within the biometric authentication dialog and the customization of the cancel button (also referred to as the negative button) that appears in the dialog.

The BiometricPrompt instance is also assigned a set of authentication callbacks that will be called to provide the app with the results of an authentication operation. A CancellationSignal instance is also used to allow the app to cancel the authentication while it is in process.

With these basics covered, the remainder of this chapter will implement fingerprint-based biometric authentication within an example project.

Creating the Biometric Authentication Project

Begin this example by launching the Android Studio environment and creating a new project, entering BiometricDemo into the Application name field and ebookfrenzy.com as the Company Domain setting before clicking on the Next button.

On the form factors screen, enable the Phone and Tablet option and set the minimum SDK setting to API 28: Android 8.0 (TBD). Continue through the setup screens, requesting the creation of an Empty Activity named BiometricDemoActivity with a corresponding layout named activity_biometric_demo.


Configuring Device Fingerprint Authentication

Fingerprint authentication is only available on devices containing a touch sensor and on which the appropriate configuration steps have been taken to secure the device and enroll at least one fingerprint. For steps on configuring an emulator session to test fingerprint authentication, refer to the chapter entitled “Using and Configuring the Android Studio AVD Emulator”.

To configure fingerprint authentication on a physical device begin by opening the Settings app and selecting the Security & Location option. Within the Security settings screen, select the Fingerprint option. On the resulting information screen click on the Next button to proceed to the Fingerprint setup screen. Before fingerprint security can be enabled a backup screen unlocking method (such as a PIN number) must be configured. If the lock screen is not already secured and follow the steps to configure either PIN, pattern or password security.

With the lock screen secured, proceed to the fingerprint detection screen and touch the sensor when prompted to do so (Figure 1-1), repeating the process to add additional fingerprints if required.

 Configuring fingerprint authentication on an Android device 

Adding the Biometric Permission to the Manifest File

Biometric authentication requires that the app request the USE_BIOMETRIC permission within the project manifest file. Within the Android Studio Project tool window locate and edit the app -> manifests -> AndroidManifest.xml file to add the permission request as follows:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.ebookfrenzy.biometricdemo">
 
    <uses-permission
        android:name="android.permission.USE_BIOMETRIC" />
.
.

Designing the User Interface

In the interests of keeping the example as simple as possible, the only visual element within the user interface will be a Button view. Locate and select the activity_biometric_demo.xml layout resource file to load it into the Layout Editor tool.

Delete the sample TextView object, drag and drop a Button object from the Common category of the palette and position it in the center of the layout canvas. Using the Attributes tool window, change the text property on the button to “Authenticate” and extract the string to a resource. Finally, configure the onClick property to call method named authenticateUser.

On completion of the above steps the layout should match that shown in Figure 1-2:

The UI layout for an Android biometric authentication example app 

Adding a Toast Convenience Method

At various points throughout the code in this example the app will be designed to display information to the user via Toast messages. Rather than repeat the same Toast code multiple times, a convenience method named notifyUser() will be added to the main activity. This method will accept a single String value and display it to the user in the form of a Toast message. Edit the FingerprintDemoActivity.java file now and add this methods as follows:

.
.
import android.widget.Toast;.
.
.
    private void notifyUser(String message) {
        Toast.makeText(this,
                message,
                Toast.LENGTH_LONG).show();
    }
.
.

Checking the Security Settings

Earlier in this chapter steps were taken to configure the lock screen and register fingerprints on the device or emulator on which the app is going to be tested. It is important, however, to include defensive code in the app to make sure that these requirements have been met before attempting to seek fingerprint authentication. These steps will be performed within the onCreate method residing in the FingerprintDemoActivity.java file, making use of the Keyguard and PackageManager manager services. Note that code has also been added to verify that the USE_BIOMETRIC permission has been configured for the app:

package com.ebookfrenzy.biometricdemo;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;


import android.widget.Toast;
import android.Manifest;
import android.content.pm.PackageManager;

import android.app.KeyguardManager;


public class BiometricDemoActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_biometric_demo);

        checkBiometricSupport();
    }

    private Boolean checkBiometricSupport() {

        KeyguardManager keyguardManager =
                (KeyguardManager) getSystemService(KEYGUARD_SERVICE);

        PackageManager packageManager = this.getPackageManager();

        if (!keyguardManager.isKeyguardSecure()) {
            notifyUser("Lock screen security not enabled in Settings");
            return false;
        }

        if (ActivityCompat.checkSelfPermission(this,
                Manifest.permission.USE_BIOMETRIC) !=
                PackageManager.PERMISSION_GRANTED) {

            notifyUser("Fingerprint authentication permission not enabled");
            return false;
        }

        if (packageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) 
        {
            return true;
        }

        return true;
    }
.
.
}

The above code changes begin by using the Keyguard manager to verify that a backup screen unlocking method has been configured (in other words a PIN or other authentication method can be used as an alternative to fingerprint authentication to unlock the screen). In the event that the lock screen is not secured the code reports the problem to the user and returns from the method.

The method then checks that the user has biometric authentication permission is enabled for the app before using the package manager to verify that fingerprint authentication is available on the device.

Configuring the Authentication Callbacks

When the biometric prompt dialog is configured, it will need to be assigned a set of authentication callback methods that can be called to notify the app of the success or failure of the authentication process. These methods need to be wrapped in a BiometricPrompt.AuthenticationCallback class instance. Remaining in the BiometricDemoActivity.java file, add a method to create and return an instance of this class with the appropriate methods implemented:

.
.
    private BiometricPrompt.AuthenticationCallback getAuthenticationCallback() {

        return new BiometricPrompt.AuthenticationCallback() {
            @Override
            public void onAuthenticationError(int errorCode, 
                                            CharSequence errString) {
                notifyUser("Authentication error: " + errString);
                super.onAuthenticationError(errorCode, errString);
            }

            @Override
            public void onAuthenticationHelp(int helpCode, 
                                         CharSequence helpString) {
                super.onAuthenticationHelp(helpCode, helpString);
            }

            @Override
            public void onAuthenticationFailed() {
                super.onAuthenticationFailed();
            }

            @Override
            public void onAuthenticationSucceeded(
                        BiometricPrompt.AuthenticationResult result) {
                notifyUser("Authentication Succeeded");
                super.onAuthenticationSucceeded(result);
            }
        };
    }
.
.
}

Adding the CancellationSignal

Once initiated, the biometric authentication process is performed independently of the app. To provide the app with a way to cancel the operation, an instance of the CancellationSignal class is created and passed to the biometric authentication process. This CancellationSignal instance can then be used to cancel the process if necessary. The cancellation signal instance may be configured with a listener which will be called when the cancellation is completed. Add a new method to the activity class to configure and return a CancellationSignal object as follows:

.
.
    private CancellationSignal getCancellationSignal() {

        cancellationSignal = new CancellationSignal();
        cancellationSignal.setOnCancelListener(new 
                         CancellationSignal.OnCancelListener() {
            @Override
            public void onCancel() {
                notifyUser("Cancelled via signal");
            }
        });
        return cancellationSignal;
    }
.
.

Starting the Biometric Prompt

All that remains is to add code to the authenticateUser() method to create and configure a BiometricPrompt instance and it initiate the authentication. Add the authenticateUser() method as follows:

public void authenticateUser(View view) {
    BiometricPrompt biometricPrompt = new BiometricPrompt.Builder(this)
            .setTitle("Biometric Demo")
            .setSubtitle("Authentication is required to continue")
            .setDescription("This app uses biometric authentication to protect your data.")
            .setNegativeButton("Cancel", this.getMainExecutor(), 
				new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int i) {
                    notifyUser("Authentication cancelled");
                }
            })
            .build();

    biometricPrompt.authenticate(getCancellationSignal(), getMainExecutor(), 
                                     getAuthenticationCallback());
}

The BiometricPrompt.Builder class is used to create a new BiometricPrompt instance configured with title, subtitle and description text to appear in the prompt dialog. The negative button is configured to display text which reads “Cancel” and a listener configured to display a message when this button is clicked. Finally, the authenticate() method of the BiometricPrompt instance is called and passed the AuthenticationCallback and CancellationSignal instances. The Biometric prompt also needs to know which thread to perform the authentication on. This is defined by passing through an Executor object configured for the required thread. In this case, the getMainExecutor() method is used to pass a main Executor object to the BiometricPrompt instance so that the authentication process takes place on the app’s main thread.

Testing the Project

With the project now complete, run the app on a physical Android device or emulator session and click on the Authenticate button to display the BiometricPrompt dialog as shown in Figure 1-3:

The Android BiometricPrompt dialog. 

Once running, either touch the fingerprint sensor or use the extended controls panel within the emulator to simulate a fingerprint touch as outlined the chapter entitled “Using and Configuring the Android Studio AVD Emulator”. Assuming a registered fingerprint is detected the prompt dialog will return to the main activity where the toast message from the successful authentication callback method will appear.

Click the Authenticate button once again, this time using an unregistered fingerprint to attempt the authentication. This time the biometric prompt dialog will indicate that the fingerprint was not recognized:

The Android BiometricPrompt class reports a failed authentication attempt


Verify that the error handling callback is working by clicking on the activity outside of the biometric prompt dialog. The prompt dialog will disappear and the toast message will be appear with the following message:

Authentication error: Fingerprint operation cancelled by user.

Check that canceling the prompt dialog using the Cancel button triggers the “Authentication Cancelled” toast message. Finally, attempt to authenticate multiple times using an unregistered fingerprint and note that after a number of attempts the prompt dialog indicates that too many failures have occurred and that future attempts cannot be made until later.

Summary

This chapter has outlined how to integrate biometric authentication into an Android app project. This involves the use the BiometricPrompt class which, once configured with appropriate message text and callbacks, automatically handles most of the authentication process.