DEV Community

Cover image for In-App Authentication Made Easy With Biometric API
Joseph Olugbohunmi
Joseph Olugbohunmi

Posted on

In-App Authentication Made Easy With Biometric API

In Android Apps nowadays, there are various forms of user authentication we get to implement such as login, verification, transaction approval and so on. Traditionally, we would authenticate users with emails, passwords, OTP and the like but what if we can authenticate a user with the security token they already use on their device such as fingerprints, face, iris, password, PIN, or pattern?

With the release of Android 10 (API level 29), a new Biometric API was introduced to help Android developers seamlessly authenticate their users with Biometrics or device credentials (password, PIN, or pattern) already registered on the device. This feature is also backwards compatible, down to Android 6 (API level 23). Integrating this library is pretty straightforward and can be done in 4 simple steps.

NB: This article is also available on Medium

Now the four simple steps…

Step 1: Add the dependency
In the App's build.gradle file, add the dependency to download the library's artifacts.

dependencies {
    ...
    implementation "androidx.biometric:biometric:${current_version}"
}
Enter fullscreen mode Exit fullscreen mode

At the time of writing this article, the version was 1.1.0

Step 2: Check if the device can perform Biometric Authentication
Do this check in onCreate() of your Activity or onViewCreated() of your Fragment.

private fun canAuthenticate(): Boolean {
    val biometricManager = BiometricManager.from(requireContext())
    return biometricManager.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_WEAK) == BiometricManager.BIOMETRIC_SUCCESS
}

if (canAuthenticate()) {
  // initializeBiometricAuth()
}
Enter fullscreen mode Exit fullscreen mode

Before now, we could just use biometricManager.canAuthenticate() but that has been deprecated for the one mentioned above where we have to pass in a type of Authenticator.

Step 3: Instantiate BiometricPrompt and build PromptInfo

private fun initializeBiometricAuth() {
        val executor: Executor = ContextCompat.getMainExecutor(context)

        val authCallback = object : BiometricPrompt.AuthenticationCallback() {

            override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
                super.onAuthenticationSucceeded(result)
                showToast("Success!")
                // proceed
            }

            override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
                super.onAuthenticationError(errorCode, errString)
                showToast("Error occurred: $errString")
            }

            override fun onAuthenticationFailed() {
                super.onAuthenticationFailed()
                showToast("Authentication failure")
            }
        }

        val biometricPrompt = BiometricPrompt(this, executor, authCallback)

        val promptInfo: BiometricPrompt.PromptInfo = BiometricPrompt.PromptInfo.Builder()
            .setTitle("Authentication")
            .setSubtitle("Subtitle")
            .setDescription("Short description")
            .setNegativeButtonText("Cancel")
            .setConfirmationRequired(true)
            .setAllowedAuthenticators(BiometricManager.Authenticators.DEVICE_CREDENTIAL)
            .build()
}
Enter fullscreen mode Exit fullscreen mode

BiometricPrompt can be constructed using 3 parameters; the context, an Executor and the AuthenticationCallback. AuthenticationCallback is an abstract class that has 3 methods; onAuthenticationError() - called when an error occurs, onAuthenticationSucceeded() - called when authentication is successful and onAuthenticationFailed() - called when authentication failed. Any of these methods can be implemented based on your requirements, but of course, onAuthenticationSucceeded() is very important.

While building BiometricPrompt.PromptInfo, you can provide any relevant information such as title, subtitle, description, and so on. Before now, we could just call setDeviceCredentialAllowed(true) but that has been deprecated for setAllowedAuthenticators() mentioned above. This method makes it possible to authenticate using a password, PIN, or pattern. Please note that when setAllowedAuthenticators(DEVICE_CREDENTIAL) is called, you cannot also call setNegativeButtonText().

Step 4: Authenticate the User
Finally, you can call the authenticate method, passing in the PromptInfo object to authenticate the user.

biometricPrompt.authenticate(promptInfo)
Enter fullscreen mode Exit fullscreen mode

This will display a Dialog with the provided information, now you can seamlessly authenticate a user in your App.

The Biometric API can also be used to perform other cryptographic operations. For advanced topics relating to the Biometric API, you can have a look at the official documentation.

Thanks for reading! If you have any observations, kindly share your thoughts in the comment section. You can also reach out to me via Twitter or LinkedIn.

Top comments (0)