21.5 C
Bangalore
September 23, 2018
Untitled
finger print
  • Home
  • Technology
  • How to integrate fingerprint authentication to your Android application?
Technology Untitled

How to integrate fingerprint authentication to your Android application?

Fingerprint authentication was introduced in Android M, a new security feature that allows users to confirm their identify with a touch. Fingerprint authentication could be a very useful addition to your apps, allowing you to secure sensitive features such as in-app payments, or replace password-and-username screens with a much more convenient single-touch sign in.

In this article, I’m going to show you how to implement fingerprint authentication in your own apps.

Creating our fingerprint authentication app

Open Android Studio and create a new project.
Once you’ve created your project, we’ll need to make some adjustments to the Manifest and build the app’s user interface.
Updating the Manifest
We need access to the device’s touch sensor in order to receive fingertip touch events. Add the following line to manifest file.

<uses-feature android:name="android.hardware.fingerprint" android:required="false"/>

When you mark android:required=”true,” the Google Play store will only allow users to install your app on devices that fulfil all of these hardware requirements.
If it’s marked false Google Play will permit users to download your app even if their device doesn’t have a fingerprint sensor. If you choose this approach, then your app will need to check presence of a touch sensor at runtime and then disable its fingerprint authentication features, where required.
Add permission to access the fingerprint sensor too:

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

Creating a Fingerprint helper class
All of the interesting stuff happens here. This class helps in setup the app for fingerprint authentication and notifies the activity/fragment about any message to be shown.
So what are the major functionalities of this class:

  • Set up a messaging mechanism to notify UI
  • Check software capabilities
  • Check hardware capabilities
  • Check app and device settings

If all the above steps are satisfied,

  • Create and set up a cipher to use with fingerprint authentication
  • Implement a callback which listens for events from fingerprint sensor
  • Start authentication
  • Cancel authentication

Step 1 is accomplished by adding a listener interface which needs to be implemented by activity/fragment listening for the events.

public interface Listener {
   void onAuthenticationError(int errorCode, CharSequence errString);
   void onAuthenticationHelp(int helpCode, CharSequence helpString);
   void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result);
   void onAuthenticationFailed();
   void onNoOSSupport();
   void onNoSensor();
   void onNoPermission();
   void onNoFingerPrints();
   void onLockScreen();
   void onCipherError();
}

Now lets focus on steps 2,3 and 4.

// If app’s minSdkVersion is anything lower than 23, then you have to verify that device is running Marshmallow or higher before executing any fingerprint-related code.

if (Build.VERSION.SDK_INT &amp;amp;gt;= Build.VERSION_CODES.M) {
   //Get an instance of KeyguardManager and FingerprintManager
   KeyguardManager keyguardManager = (KeyguardManager) context.getSystemService(KEYGUARD_SERVICE);
   mFingerprintManager = (FingerprintManager) context.getSystemService(FINGERPRINT_SERVICE);

   //Check whether device has a fingerprint sensor
   if (!mFingerprintManager.isHardwareDetected()) {
       // If a fingerprint sensor isn’t available, then inform UI that
       // they will be unable to use fingerprint functionality
       listener.onNoSensor();
       return;
   }

   //Check whether user has granted the USE_FINGERPRINT permission
   if (ActivityCompat.checkSelfPermission(context, Manifest.permission.USE_FINGERPRINT)
           != PackageManager.PERMISSION_GRANTED) {
       // If app doesn't have this permission, then notify user
       listener.onNoPermission();
       return;
   }

   //Check user has registered at least one fingerprint
   if (!mFingerprintManager.hasEnrolledFingerprints()) {
       // If user hasn’t configured any fingerprints, then notify user
       listener.onNoFingerPrints();
       return;
   }

   //Check that the lockscreen is secured
   if (!keyguardManager.isKeyguardSecure()) {
       // If the user hasn’t secured their lockscreen with a PIN or pattern,
       listener.onLockScreen();
       return;
   }
} else {
   listener.onNoOSSupport();
}

Now for step 5 generate a cipher.

private Cipher generateCipher() {
   try {
       // Obtain reference to the Standard Android Keystore
       KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
       //Get an instance of key generator
       KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
       //Initialize keystore
       keyStore.load(null);

       //Initialize the KeyGenerator
       keyGenerator.init(
               new KeyGenParameterSpec.Builder(KEY_NAME, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
                       .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
                       //Configure this key so that the user has to confirm their identity with
                       // a fingerprint each time
                       .setUserAuthenticationRequired(true)
                       .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
                       .build());

       //Generate the secret key
       SecretKey key = keyGenerator.generateKey();

       //Obtain a Cipher instance and configure it with the properties required for
       // fingerprint authentication
       Cipher cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/"
               + KeyProperties.BLOCK_MODE_CBC + "/"
               + KeyProperties.ENCRYPTION_PADDING_PKCS7);
       cipher.init(Cipher.ENCRYPT_MODE, key);
       return cipher;
   } catch (KeyStoreException
           | NoSuchAlgorithmException
           | NoSuchProviderException
           | InvalidAlgorithmParameterException
           | CertificateException
           | NoSuchPaddingException
           | InvalidKeyException
           | IOException exc) {
       exc.printStackTrace();
       return null;
   }
}

Create a crypto object using the cipher instance. This crypto object will be used later for fingerprint authentication.

Cipher cipher = generateCipher();
if (cipher != null) {
   //If the cipher is initialized successfully, then create a CryptoObject instance
   mCryptoObject = new FingerprintManager.CryptoObject(cipher);
} else {
   listener.onCipherError();
}

Step 6 is achieved by implementing FingerprintManager.AuthenticationCallback. This callback implementation is required to listen for events from fingerprint manager.

mAuthCallback = new FingerprintManager.AuthenticationCallback() {
   @Override
   public void onAuthenticationError(int errorCode, CharSequence errString) {
       mListener.onAuthenticationError(errorCode, errString);
   }

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

   @Override
   public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
       mListener.onAuthenticationSucceeded(result);
   }

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

Now step 7. Create a method to start authentication. This method will be called from activity/fragment when it is ready to scan the finger print.

public void startAuth() {
   if (Build.VERSION.SDK_INT &amp;amp;gt;= Build.VERSION_CODES.M) {
       //Used later to cancel authentication.
       mCancellationSignal = new CancellationSignal();
       mFingerprintManager.authenticate(mCryptoObject, mCancellationSignal, 0, mAuthCallback, null);
   }
}

For step 8, create a method to cancel authentication when appropriate.

public void cancel() {
   if (mCancellationSignal != null) {
       mCancellationSignal.cancel();
   }
}

Create UI for our sample app.

Main elements in UI would be,

  • Implement FingerPrintHandler.Listener
  • Create an instance of FingerPrintHandler
  • Add a button to start authentication process
  • Cancel authentication

First we will create a fingerprint icon. Right click on drawable folder of your project. Select New->Vector Asset. Choose finger print icon from the list.
Now we have all our resources, let’s create our UI:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical">

   <ImageView android:id="@+id/finger" android:layout_width="100dp" android:layout_height="100dp" android:src="@drawable/ic_fingerprint" android:layout_gravity="center_horizontal" android:layout_marginTop="50dp"/>

   <TextView android:id="@+id/instruction" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/instructions" android:layout_marginTop="20dp" android:layout_gravity="center_horizontal"/>
</LinearLayout>

Your user interface should look something like this:

Lets enable the buttons and listen for events. Make MainActivity implement FingerPrintHandler.Listener.
Also create an instance of FingerPrintHandler and call startAuth() when tapping on finger print ImageView we just added.

public class MainActivity extends AppCompatActivity implements FingerPrintHandler.Listener {

   FingerPrintHandler mFingerPrintHandler;

   private TextView mInstructionsTV;
   private ImageView mIconView;

   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);
       mInstructionsTV = findViewById(R.id.instruction);
       mIconView = findViewById(R.id.finger);

       mFingerPrintHandler = new FingerPrintHandler(getApplicationContext(), this);
       mIconView.setOnClickListener(new View.OnClickListener() {
           @Override
           public void onClick(View view) {
               mFingerPrintHandler.startAuth();
               mInstructionsTV.setText(R.string.instructions2);
           }
       });
   }

   @Override
   protected void onDestroy() {
       mFingerPrintHandler.cancel();
       super.onDestroy();
   }

Call cancel() method in onDestroy(). This will release reference to the sensor when our app no longer requires it.

Source code for this sample app is available in github.
https://github.com/jacksvarghese86/FingerPrintAuthentication
If you want to integrate finger print authentication to your existing project, all you need is to add the FingerPrintHelper class and implement the FingerPrintHelper.Listener

Related posts