Android Authentication Using Kotlin

2874 VIEWS

Authentication in layman’s terms is the process of proving something to be valid. When we have a computer system and a designated end-user, we will want to assert the identity of that end-user. We accomplish this process by authentication. Authentication methods vary across programming languages, but in this article we will like to shed some light on Android authentication using Kotlin. Biometrics is the most common means of asserting the identity of an end-user. Therefore, we will guide you on how to authenticate fingerprints using plain old Kotlin.

Prerequisites
  • Kotlin
  • Code editor (preferably Android Studio)
  • Coffee 
Aim

This tutorial guides the reader on how to authenticate the identity of a user using their fingerprint.

Note: we will use a physical emulator that already serves as a fingerprint manager, so we will not implement that aspect in our project.

Creating a New Project

Firstly, we must create a new Kotlin project in our code editor. To do this, we will follow the steps below:

  1.  We will start by selecting a new project in our Android Studio.
  2. After, we want a simple template; thus, we will select empty activity as our project template.
  3. Then we will need to set a name for our application. You can use any name of your choice, but we will call it FingerprintAuth for the tutorial’s sake.
  4. Finally, click on finish, and you are good to go!

We want to start by designing the user interface, but before proceeding, we will add the biometric dependency to our build.gradle(:app) file.

implementation("androidx.biometric:biometric:1.2.0-alpha04")

We want to add a button and text for our user interface. To do this, we will start by clearing the default Textview and add a button to our activity_main.xml file. Below is the implementation of the button:

<Button
  android:id="@+id/Authbtn"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:text="Authenticate Now"
  app:layout_constraintBottom_toBottomOf="parent"
  app:layout_constraintEnd_toEndOf="parent"
  app:layout_constraintStart_toStartOf="parent"
  app:layout_constraintTop_toTopOf="parent" />

In Kotlin, we can add buttons also using a drag and drop method. In order to do this, head to the design section in your activity_main.xml, select palette, and you will see Android widgets to drag and drop into your design.

Next, we will add a Textview into our xml code and within it, we will specify its name, text size, and constraints. Below is the implementation of the Textview:

<TextView
  android:id="@+id/textView"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:text="Auth status"
  android:textColor="@color/white"
  android:textSize="25dp"
  app:layout_constraintEnd_toEndOf="parent"
  app:layout_constraintStart_toStartOf="parent"
  app:layout_constraintTop_toBottomOf="@+id/Authbtn" />

Here is what our user interface looks like at the moment:

Binding the XML Layout

Some time ago, app developers widely used Kotlin synthetics to bind Android views, but now it has been deprecated. Also, one of the popular ways to bind views in Kotlin is using databinding (an alternative to Viewbinding) and findviewbyid.

This section entails all the functionalities of our project, and to implement them, we will head back to the MainActivity.kt file to set up the biometrics. We start by binding our views in our activity_main.xml file to the MainActivity.kt file. In order to do this, we will use Viewbinding.

Viewbinding is a feature that allows you to seamlessly interact with your views by creating a binding class for each XML layout file present in the module. Below is a step-by-step process on how to implement Viewbinding in Kotlin:

  • Head to the build.gradle(:app) file and add the block below to the Android block. After, sync the gradle file.
    buildFeatures {
      viewBinding true
    }
  • Next, in the MainActivity.kt file, create a private lateinit var called binding and give it the type ActivityMainBinding, which is the binding class generated by Viewbinding.
  • Finally, we will initialize the binding variable and set the content view. We have the implementation in the code below:
    binding = ActivityMainBinding.inflate(layoutInflater)
    setContentView(binding.root)

Biometric Authentication

We have bound the XML layout to the Kotlin file, and now, we want to implement the functionalities for the biometric authenticator. Following this, we will need to create three classes; Executor, BiometricPrompt, BiometricPrompt.PromptInfo.

Thus, we will start by creating three private lateinit variables for these three classes (executor, biometricprompt, promptinfo), and they are as below:

private lateinit var executor: Executor
private lateinit var biometricPrompt: androidx.biometric.BiometricPrompt
private lateinit var promptInfo: androidx.biometric.BiometricPrompt.PromptInfo

Next, we will initialize the three variables and set a click listener for the button. Thus, once we click the button, it triggers the promptInfo.

We have the code below:

executor = ContextCompat.getMainExecutor(this)

biometricPrompt =androidx.biometric.BiometricPrompt(this@MainActivity,executor,object:androidx.biometric.BiometricPrompt.AuthenticationCallback(){

  @SuppressLint("SetTextI18n")
  override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
    super.onAuthenticationError(errorCode, errString)
    binding.Authstatus.text = "Error, $errString"
  }

  @SuppressLint("SetTextI18n")
  override fun onAuthenticationSucceeded(result: androidx.biometric.BiometricPrompt.AuthenticationResult) {
    super.onAuthenticationSucceeded(result)
    binding.Authstatus.text = "Successful auth"
  }

  @SuppressLint("SetTextI18n")
  override fun onAuthenticationFailed() {
    super.onAuthenticationFailed()
    binding.Authstatus.text = "Authentication Failed"
  }
})

promptInfo= androidx.biometric.BiometricPrompt.PromptInfo.Builder()
  .setTitle("Biometric Authentication")
  .setSubtitle("Login using fingerprint or face")
  .setNegativeButtonText("Cancel")
  .build()
binding.Authbtn.setOnClickListener {
  biometricPrompt.authenticate(promptInfo)
}
Explaining the Code Snippet
  • ontextCompat.getMainExecutor — this method returns an executor that will run the enqueued task on the primary thread associated with this context.
  • AuthenticationCallback() — this is a nested class within BiometricPrompt, and it contains three public methods:

Now, our complete code and result for the MainActivity.kt file and project, respectively, will be as below:

package com.example.fingerprintauth

import android.annotation.SuppressLint
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import com.example.fingerprintauth.databinding.ActivityMainBinding
import java.util.concurrent.Executor

class MainActivity : AppCompatActivity() {
  private lateinit var binding: ActivityMainBinding

  private lateinit var executor: Executor
  private lateinit var biometricPrompt: androidx.biometric.BiometricPrompt
  private lateinit var promptInfo: androidx.biometric.BiometricPrompt.PromptInfo

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = ActivityMainBinding.inflate(layoutInflater)
    setContentView(binding.root)

    executor = ContextCompat.getMainExecutor(this)

    biometricPrompt =androidx.biometric.BiometricPrompt(this@MainActivity,executor,object:androidx.biometric.BiometricPrompt.AuthenticationCallback(){

      @SuppressLint("SetTextI18n")
      override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
        super.onAuthenticationError(errorCode, errString)
        binding.Authstatus.text = "Error, $errString"
      }

      @SuppressLint("SetTextI18n")
      override fun onAuthenticationSucceeded(result: androidx.biometric.BiometricPrompt.AuthenticationResult) {
        super.onAuthenticationSucceeded(result)
        binding.Authstatus.text = "Successful auth"
      }

      @SuppressLint("SetTextI18n")
      override fun onAuthenticationFailed() {
        super.onAuthenticationFailed()
        binding.Authstatus.text = "Authentication Failed"
      }
    })

    promptInfo= androidx.biometric.BiometricPrompt.PromptInfo.Builder()
      .setTitle("Biometric Authentication")
      .setSubtitle("Login using fingerprint or face")
      .setNegativeButtonText("Cancel")
      .build()

    binding.Authbtn.setOnClickListener {
      biometricPrompt.authenticate(promptInfo)
    }
  }
}

Conclusion

Authentication in any form is necessary for any programming language when you want to assert the identity of a user. This tutorial has walked you through using authentication, specifically biometric authentication, with Kotlin. Thanks for reading, and happy coding!


Muyiwa Femi-ige is a technical writer who has a knack for putting codes and coding processes into a well documented format.


Discussion

Leave a Comment

Your email address will not be published. Required fields are marked *

Menu
Skip to toolbar