avatarMichal Ankiersztajn

Summary

The web content provides a comprehensive guide on implementing biometric authentication in Android applications using the BiometricManager API, covering dependency declaration, authentication type selection, availability checks, prompt creation, and emulator debugging.

Abstract

The article outlines the process of integrating biometric authentication into Android apps using the AndroidX Biometric API. It begins by emphasizing the importance of biometric security for sensitive data, particularly in financial and healthcare sectors. The guide then proceeds through several key steps: adding the necessary AndroidX Biometric dependency, selecting the appropriate level of biometric authentication (strong or weak), verifying the availability of biometric sensors, creating a biometric prompt with user-friendly messages and optional fallback mechanisms, and handling various authentication outcomes. Additionally, the article addresses debugging biometric authentication on Android emulators and suggests using a CryptoObject for enhanced security when needed.

Opinions

  • The author suggests that biometric authentication is crucial for apps handling sensitive information, implying its effectiveness in securing user data.
  • The choice between strong and weak biometric authentication is left to the developer, with a preference for strong authentication where possible, as indicated by the example code provided.
  • There is an acknowledgment that not all devices may support biometric authentication, and the article provides guidance on prompting users to enroll in biometrics if necessary.
  • The inclusion of a negative button in the biometric prompt dialog is recommended, offering users an alternative authentication method, demonstrating user experience considerations.
  • The article encourages developers to test biometric features thoroughly using Android emulators, highlighting the importance of comprehensive testing before deployment.
  • The author provides a link to an example GitHub repository, implying that real-world code examples can greatly assist developers in understanding and implementing new features.
  • By mentioning the use of CryptoObject for biometric authentication, the author conveys an opinion that security should not be an afterthought and should be integrated from the start.

Android Biometric Authentication With BiometricManager

This is one of the methods to protect sensitive information. Biometric Authentication is a way for users to authenticate using face or fingerprint recognition. It’s very important especially for financial and healthcare apps that require authentication every time the user opens the app.

Biometric Example App

For those that want to jump straight to the code:

1. Declare the dependency:

You can check the latest release here.

dependencies {
    implementation("androidx.biometric:biometric:1.1.0")
    ...
}

2. Choose Authentication Type

  • BIOMETRIC_STRONGClass 3 biometric, find out more about it here
  • BIOMETRIC_WEAKClass 2 biometric, find out more about it here
  • DEVICE_CREDENTIAL — User is prompted with LockScreen PIN/Pattern/Password

I won’t go into much detail about the differences between STRONG and WEAK as it would be too long a topic. You can read about them in the most recent Android version docs. https://source.android.com/docs/compatibility/14/android-14-cdd?hl=en#7310_biometric_sensors

You can also choose multiple types together: BIOMETRIC_STRONG or DEVICE_CREDENTIAL

3. Check whether the Authentication is available

Double-check imports to make sure you’re using androidx.biometric.*

I’ll use BIOMETRIC_STRONGin the following examples. Some devices might not have biometric Authentication. Here we have 4 possibilities:

val biometricManager = BiometricManager.from(this)
when (biometricManager.canAuthenticate(BIOMETRIC_STRONG)) {
    BiometricManager.BIOMETRIC_SUCCESS -> {
        // Authenticate using biometrics
    }

    BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE -> {
        // Biometric features hardware is missing
    }

    BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE -> {
        // Biometric features are currently unavailable.
    }

    BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED -> {
        // The user didn't enroll in biometrics that your app accepts, prompt them to enroll in it
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            val enrollIntent =
                Intent(Settings.ACTION_BIOMETRIC_ENROLL).apply {
                    putExtra(
                        Settings.EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED,
                        BIOMETRIC_STRONG or DEVICE_CREDENTIAL
                    )
                }
            startActivityForResult(enrollIntent, REQUEST_CODE)
        }
    }
}

4. Create the Prompt

If we received BIOMETRIC_SUCCESSwe can prompt the user with the biometric authentication dialog. We’ll need 2 things:

  • Dialog called PromptInfo
private fun createPromptInfo(): BiometricPrompt.PromptInfo =
    BiometricPrompt.PromptInfo.Builder()
        .setTitle("Authenticate with biometrics")
        .setAllowedAuthenticators(BIOMETRIC_STRONG)
        .setConfirmationRequired(false)
        .setNegativeButtonText("Login with password")
        .build()
  • Prompt with callback
private fun createBiometricPrompt(): BiometricPrompt {
    val callback = object : BiometricPrompt.AuthenticationCallback() {
        override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
            super.onAuthenticationError(errorCode, errString)
            if (errorCode == BiometricPrompt.ERROR_NEGATIVE_BUTTON) {
                // If you've added negative button to prompt dialog
            }
        }

        override fun onAuthenticationFailed() {
            super.onAuthenticationFailed()
            // Failure with unknown reason
        }

        override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
            super.onAuthenticationSucceeded(result)
            // Authenticated successfully!
        }
    }

    val executor = ContextCompat.getMainExecutor(this)
    return BiometricPrompt(this, executor, callback)
}

5. Show the prompt

Now that we have all set, you can show the prompt:

BiometricManager.BIOMETRIC_SUCCESS -> {
    val prompt = createBiometricPrompt()
    prompt.authenticate(createPromptInfo())
}

If the user authenticates successfully, the onAuthenticationSuceeded inside the callback will be invoked.

BONUS: Debugging Biometrics on Emulator

If you want to debug Biometrics on Emulator, you’ll need to add a Lock Screen and Fingerprint, which you should get prompted for when trying to unlock with biometrics. You can test Fingerprint in the emulator by following the steps in this image:

How to debug Fingerprints on Emulator

If you’ve had trouble setting it all up, clone the example app to see how it works together:

There is also the possibility of using BiometricAuthentication with CryptoObject. If that’s what you need, check out this guide.

If you’ve learned something new and want others to find it too, please 👏 and follow me for more.

Based on:

AndroidDev
Android App Development
Android Biometric Auth
Biometricmanager
Androidfingerprint
Recommended from ReadMedium