Skip to main content

Implementing Biometric Authentication in Android with Jetpack Compose- A Step-by-Step Guide

· 13 min read
Petros Efthymiou

Biometric Authentication in Android

Introduction

In today's digital landscape, security and user experience are paramount considerations for developers creating Android applications. Biometric authentication, a revolutionary advancement in mobile security, has emerged as a pivotal solution that addresses both security concerns and user convenience. With the rise of data breaches and the increasing dependency on mobile devices for various transactions, implementing robust authentication mechanisms is non-negotiable.

Biometric authentication is a cutting-edge method that leverages the unique physiological and behavioral characteristics of an individual to grant access to applications and sensitive data. Instead of relying solely on traditional methods like PINs or passwords, biometric authentication harnesses distinctive traits such as fingerprints, facial features, and iris patterns to verify a user's identity.

Advantages of Biometric Authentication

  1. Enhanced Security: Biometric authentication offers a higher level of security compared to traditional methods. Unlike passwords or PINs, which can be forgotten, shared, or hacked, biometric characteristics are unique to each individual. Having said that, there are security gaps in biometrics as well, such as authentication false positives due to poor device hardware, but those can be mitigated, as we will see later. Another opportunity to bypass it might be malicious fingerprint capturing (with photos or other methods) for user imitation.

  2. User Convenience: One of the standout benefits of biometric authentication is its ease of use. Users no longer need to remember complex passwords or worry about typing errors. A simple touch of a finger or a glance at the camera is all it takes to gain access. This frictionless experience not only reduces user frustration but also encourages secure behavior.

  3. Seamless Interaction: Biometric authentication seamlessly integrates into the user's natural interaction with the device. It eliminates the need to switch between apps to retrieve passwords or codes, streamlining the user journey and increasing overall efficiency.

  4. Reduced Friction: Traditional authentication methods often lead to abandoned sign-up or login processes due to the cumbersome nature of password entry. Biometric authentication reduces this friction, leading to higher user engagement and retention rates.

  5. Multifactor Authentication: Many modern devices support multifactor authentication, combining biometric traits with other factors such as PINs or tokens. This layered approach further enhances security by adding an extra barrier against unauthorized access.

In this step-by-step guide, we will explore how to implement biometric authentication in Android applications using the power of Jetpack Compose. To read more about Jetpack Compose you may visit our article. By combining the capabilities of Jetpack Compose with the Android Biometric API, developers can craft applications that prioritize security and provide a seamless and delightful user experience.

In the following sections, we will walk through the process of integrating biometric authentication into an Android app using Jetpack Compose. We will cover various aspects such as understanding the Biometric API, preparing the project, implementing different biometric modalities, and ensuring security best practices.

Stay tuned as we embark on this journey to create more secure, user-centric, and innovative Android applications with the power of biometric authentication and Jetpack Compose.

Understanding Biometric Authentication

Android devices offer several biometric modalities, each with its own set of characteristics and advantages.

Fingerprint Authentication:

Fingerprint authentication is one of the most widely recognized biometric methods. It relies on capturing and analyzing the distinctive patterns in a user's fingerprints. As every individual has unique ridge patterns and minutiae points at their fingertips, fingerprint authentication offers a high level of accuracy and security. Android devices equipped with fingerprint sensors enable users to unlock their devices, authorize transactions, and access sensitive apps simply by placing their registered finger on the sensor. This method has gained significant popularity due to its ease of use and quick recognition.

Face Recognition:

Face recognition involves capturing and analyzing a user's facial features to establish identity. It works by detecting key facial landmarks and comparing them with registered data. The minimum hardware requirement is a high-resolution camera. This camera should have sufficient resolution and quality to detect facial features accurately. To enhance security, some phones carry depth sensors that create a 3D depth map of the user's face. Or, even better, an infrared camera that enables IRIS recognition. Just with a front-facing camera, the device is considered to have weak biometric authentication.

Face recognition is convenient and non-intrusive, providing a seamless user experience. However, it's important to note that lighting conditions and angle variations can impact its accuracy.

Iris Recognition:

Iris recognition is a highly secure biometric method that involves capturing and analyzing the unique patterns in a user's iris, which is the colored part of the eye surrounding the pupil. Like fingerprints, iris patterns are distinct to each individual and remain stable over time. This method offers a higher degree of accuracy and security due to the complexity of the iris patterns. While iris recognition may require specific hardware, it provides a robust solution for applications that demand stringent security measures.

The Role of Biometric Authentication in App Security:

Biometric authentication plays a crucial role in enhancing the security of sensitive app functionalities. While traditional authentication methods like passwords can be compromised through hacking, phishing, or even user negligence, biometric traits are inherent and difficult to replicate. By incorporating biometric authentication as an additional security layer, apps can ensure that only authorized individuals gain access to critical features, sensitive data, and financial transactions.

For instance, financial apps can use biometric authentication to authorize high-value transactions, ensuring that even if a user's device is stolen, unauthorized transactions cannot be carried out without the user's biometric input. Similarly, healthcare apps can use biometrics to secure patient records and medical data, safeguarding sensitive information from unauthorized access.

The significance of biometric authentication extends beyond security. By reducing the need for complex passwords and PINs, biometrics offer a seamless and user-friendly experience, contributing to higher user engagement and satisfaction. Users are more likely to adopt apps that prioritize both security and convenience.

As we proceed through this step-by-step guide, we will explore how to harness the power of Jetpack Compose to integrate biometric authentication seamlessly into your Android apps. By combining the strength of biometric modalities with the modern UI capabilities of Jetpack Compose, you'll be able to create applications that are not only secure but also delightful to use. Stay with us as we dive deeper into the implementation details and unlock the potential of biometric authentication in your Android projects.

Prerequisites

Before diving into the implementation of biometric authentication in your Android app using Jetpack Compose, there are several prerequisites that you need to ensure are in place. These prerequisites ensure that your app can effectively utilize the Biometric API and provide a seamless and secure user experience.

Minimum SDK Version:

To implement biometric authentication, your app should have a minimum SDK version of 23 (Android 6.0, Marshmallow) or higher, as the Biometric API was introduced in this version.

Hardware Requirements:

The availability of biometric authentication methods depends on the hardware capabilities of the user's device. Such as:

  • Fingerprint sensor for fingerprint authentication.
  • Front-facing Camera for facial recognition.
  • Infrared camera for iris recognition.

Ensure that your app gracefully handles scenarios where the required hardware is not available on the device.

Setting Up Biometric Authentication and Jetpack Compose

Now that we've covered the prerequisites, it's time to set up your Android project for biometric authentication using the Android Biometric API and Jetpack Compose. This section will guide you through adding the necessary permissions and dependencies to your project, ensuring that you're well-equipped to integrate biometric authentication seamlessly into your app.

  1. Adding Permissions:

Depending on the biometric modality you plan to use, you may need to add specific permissions to your app's AndroidManifest.xml file. For example, if you intend to use face recognition, you must request CAMERA permission to access the front-facing camera:

<uses-permission android:name="android.permission.CAMERA" />

Make sure to request permissions at runtime if your app targets Android 6.0 (Marshmallow) or higher. You can use the AndroidX Activity or Fragment libraries to handle permission requests effectively.

  1. Adding Dependencies:

To begin implementing biometric authentication using the Android Biometric API and Jetpack Compose, you must add the required dependencies to your app's build.gradle file. We'll be using the Biometric API to interact with biometric hardware and the Jetpack Compose libraries for UI creation.

In your app's build.gradle file, add the following dependencies:

android {
// ...
buildFeatures {
compose true
}

composeOptions {
kotlinCompilerExtensionVersion "1.5.1"
}
}

dependencies {
// ...
implementation "androidx.compose.ui:ui:1.4.3"
implementation "androidx.compose.material:material:1.4.3" // Check for the latest version
implementation "androidx.activity:activity-compose:1.7.2"
implementation("androidx.biometric:biometric:1.2.0-alpha05")

}

The androidx.compose and androidx.activity:activity-compose are required for building the user interface using Jetpack Compose.

The androidx.biometric:biometric dependency provides access to the Android Biometric API, which is essential for implementing biometric authentication.

Checking Biometric Device Compatibility

Now, let’s start implementing the actual solution. As we are using Jetpack Compose we will create a MainActivity and add our Composables to it.

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
BiometricAuthenticationScreen()
}
}
}

We now need to implement the BiometricAuthenticationScreen Composable that will be responsible for the actual biometric authentication.

@Composable
fun BiometricAuthenticationScreen() {
val context = LocalContext.current as FragmentActivity
val biometricManager = BiometricManager.from(context)
val canAuthenticateWithBiometrics = when (biometricManager.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_STRONG)) {
BiometricManager.BIOMETRIC_SUCCESS -> true
else -> {
Log.e("TAG", "Device does not support strong biometric authentication")
false
}
}

Surface(color = MaterialTheme.colors.background) {
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
if (canAuthenticateWithBiometrics) {
//TODO perform biometric authentication
} else {
Text(text = "Biometric authentication is not available on this device.")
}
}
}
}

We have implemented a simple Composable that first of all is using the BiometricManager to identify whether biometric authentication is available on this device. It stores the result on a boolean value. As we explained earlier there are devices, particularly older devices, that do not support any fingerprint, face, or iris authentication.

In our implementation are logging those cases and presenting a text on the screen that informs the user. In a real-world app, we would probably want to redirect the user to a username-password authentication screen instead.

Implementing Biometric Authentication

Let’s proceed with implementing the biometric authentication. First of all, we will create a button Composable that will appear on the screen when the device supports biometric authentication.

@Composable
fun BiometricButton(
onClick: () -> Unit,
text: String
) {
Button(
onClick = onClick,
modifier = Modifier.padding(8.dp)
) {
Text(text = text)
}
}

Now we will implement the authenticate with biometric function.

fun authenticateWithBiometric(context: FragmentActivity) {
val executor = context.mainExecutor
val biometricPrompt = BiometricPrompt(
context,
executor,
object : BiometricPrompt.AuthenticationCallback() {
override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
//TODO handle authentication success, proceed to HomeScreen
Log.d("TAG", "Authentication successful!!!")
}

override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
Log.e("TAG", "onAuthenticationError")
//TODO Handle authentication errors.
}

override fun onAuthenticationFailed() {
Log.e("TAG", "onAuthenticationFailed")
//TODO Handle authentication failures.
}
})

val promptInfo = BiometricPrompt.PromptInfo.Builder()
.setTitle("Biometric Authentication")
.setDescription("Place your finger the sensor or look at the front camera to authenticate.")
.setNegativeButtonText("Cancel")
.setAllowedAuthenticators(BiometricManager.Authenticators.BIOMETRIC_STRONG)
.build()

biometricPrompt.authenticate(promptInfo)
}

Initially, we are creating a Biometric Prompt with the respective callbacks that decide what happens on each occasion. The onAuthenticationSucceedded callback is called when the authentication is successful, here you probably want to include an Intent for your HomeActivity or present your HomeScreen Composable. Personally, I prefer to separate the pre-authentication app from the post-authentication app with a separate activity.

After we create the BiometricPrompt we also create the PromptInfo that defines the options and literals that will present to the user when he triggers the biometric authentication.

Then we define what authenticators we want to allow. Here we are requesting the BIOMETRIC_STRONG type of authentication. This includes:

  1. Fingerprint authentication.
  2. Face recognition with IRIS detection.
  3. Face recognition with a 3D depth sensor.

As we mentioned earlier, a device that only carries a front-facing camera cannot apply strong biometric authentication. The OS is picking automatically the strong authentication option that is available on the current device (fingerprint or face recognition). Usually, devices don’t carry more than 1 strong-biometric authentication sensors, as this would unnecessarily increase their cost.

Finally, we call the authenticate function on the biometricPrompt to trigger the actual authentication popup.

In order to finalize the implementation, we need to display the BiometricButton on the devices that support biometric authentication. Replace the //TODO perform biometric authentication with BiometricButton(...)

    Surface(color = MaterialTheme.colors.background) {
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
if (canAuthenticateWithBiometrics) {
BiometricButton(
onClick = {
authenticateWithBiometric(context)
},
text = "Authenticate with Biometric"
)
} else {
Text(text = "Biometric authentication is not available on this device.")
}
}
}

The implementation is completed! You can now build and install the app on a device that supports biometrics and perform the authentication!

Biometric Authentication Error Handling

Let’s now discuss the error handling of biometric authentication.

Both onAuthenticationError and onAuthenticationFailed are callback methods of the BiometricPrompt.AuthenticationCallback class. These methods are invoked based on different scenarios during the biometric authentication process.

onAuthenticationError Method:

The onAuthenticationError method is called when an error occurs during the biometric authentication process. This could include various types of errors, such as the user clicking the cancel button, sensor errors, hardware issues, or other unexpected conditions that prevent successful authentication. The method receives two parameters:

  1. errorCode: An integer code representing the specific error that occurred. This code can be used to identify the nature of the error.
  2. errString: A human-readable error message that provides additional details about the error.

onAuthenticationFailed Method:

The onAuthenticationFailed method is called when the biometric authentication process fails to recognize the biometric data provided by the user. This can occur when the biometric data presented to the sensor does not match any enrolled biometric template. It's important to note that this callback is not invoked for every unsuccessful attempt; it's specifically for cases where the biometric data provided cannot be matched to any registered data.

Similar to the onAuthenticationError method, the onAuthenticationFailed method should be used to handle authentication failures by implementing appropriate logic.

In summary, onAuthenticationError is called when there's an error during the authentication process, and onAuthenticationFailed is called when the provided biometric data cannot be matched to any registered data. Both methods are essential for creating a comprehensive biometric authentication experience that informs users about errors and failures and guides them through the authentication process.

Conclusion

As we conclude this step-by-step guide on implementing biometric authentication in Android with Jetpack Compose, we've explored the fusion of cutting-edge security measures and user-centric design principles. Biometric authentication has emerged as a formidable solution that not only enhances the security of your Android applications but also elevates the user experience to new heights.

By harnessing the power of biometric modalities such as fingerprint, face recognition, and iris authentication, developers can provide users with a seamless and secure way to access sensitive features, authenticate transactions, and interact with confidential data. The integration of Jetpack Compose further amplifies the potential, enabling the creation of intuitive and visually appealing user interfaces that align with modern design trends.

Shipbook provides awesome remote logging capabilities that can help you identify, debug, and fix critical authentication errors at the time they appear!

Thank you for joining us on this exploration of biometric authentication with Jetpack Compose. As technology continues to evolve, we encourage you to stay curious, experiment, and continually enhance your skills to build exceptional and secure experiences for Android users worldwide.