Search code examples
javaandroidauthenticationandroid-securityandroid-biometric-prompt

BiometricPrompt Error cases for onAuthenticationError() after update to latest version


I have updated the version of a library from: `

from 'androidx.biometric:biometric:1.0.1' to -> 'androidx.biometric:biometric:1.1.0'

I saw that there are new possible errors and I was wondering how to handle them!

Ide show error warning for switch statement:

"Switch statement on an int with known associated constant missing case 
 BiometricPrompt.ERROR_HW_NOT_PRESENT,
 BiometricPrompt.ERROR_HW_UNAVAILABLE, 
 BiometricPrompt.ERROR_NO_BIOMETRICS, 
 BiometricPrompt.ERROR_NO_DEVICE_CREDENTIAL, 
 BiometricPrompt.ERROR_NO_SPACE, 
 BiometricPrompt.ERROR_TIMEOUT, 
 BiometricPrompt.ERROR_UNABLE_TO_PROCESS,
 BiometricPrompt.ERROR_VENDOR"

That's my code before updating of library:

private class BioCallback extends AuthenticationCallback {
   public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) {
    switch (errorCode) {
        case ERROR_CANCELED:
        case ERROR_USER_CANCELED:
            endAuth(false);
            runOnUiThread(() -> {
                try {
                    mBiometricPrompt.authenticate(mPromptInfo);
                } catch (Exception e) {
                    FirebaseUtil.logEvent("cmc_crash_fingerprint");
                }
            });
            break;
        case ERROR_NEGATIVE_BUTTON:
        case ERROR_LOCKOUT:
        case ERROR_LOCKOUT_PERMANENT:
        default:
            endAuth(false);
            showLoginScreen();
            break;
    }
    super.onAuthenticationError(errorCode, errString);
   }

After I read documentation for each Error Code I change the code to:

switch (errorCode) {
    case ERROR_CANCELED:
    case ERROR_USER_CANCELED:
    case ERROR_TIMEOUT:
    case ERROR_NO_SPACE:
    case ERROR_UNABLE_TO_PROCESS:
        endAuth(false);
        runOnUiThread(() -> {
            try {
                mBiometricPrompt.authenticate(mPromptInfo);
            } catch (Exception e) {
                FirebaseUtil.logEvent("cmc_crash_fingerprint");
            }
        });
        break;
    case ERROR_NEGATIVE_BUTTON:
    case ERROR_LOCKOUT:
    case ERROR_LOCKOUT_PERMANENT:
    case ERROR_HW_NOT_PRESENT:
    case ERROR_HW_UNAVAILABLE:
    case ERROR_NO_DEVICE_CREDENTIAL:
    case ERROR_NO_BIOMETRICS:
    case ERROR_VENDOR:
    default:
        endAuth(false);
        showLoginScreen();
        break;
}

Is that the best choice and are there some hidden problems with it?

Thank you very much in advance :).


Solution

  • So looking at all of these new error types:

    BiometricPrompt.ERROR_HW_NOT_PRESENT, BiometricPrompt.ERROR_HW_UNAVAILABLE - these two indicate that the hardware required for biometrics is not present/available. There is no way to do biometric auth so your handling seems correct.

    BiometricPrompt.ERROR_VENDOR - vendor-specific problem, there is nothing you can do so ending auth and failing seems again correct.

    BiometricPrompt.ERROR_UNABLE_TO_PROCESS, - sensor was not able to process the image, most likely something is wrong with the sensor. Again there is not much you can do from the app's side, your handling seems correct.

    BiometricPrompt.ERROR_TIMEOUT - just a timeout(the user hasn't taken any action with the prompt for a long time). There is no point in waiting for user action indefinitely. The only thing you might want to consider is whether you want to show the prompt again(as you are doing in your handling) your handling or you want just mark it as failed and cancel, but in general, handling is correct.

    BiometricPrompt.ERROR_NO_BIOMETRICS, BiometricPrompt.ERROR_NO_DEVICE_CREDENTIAL - these two are connected because there are three classes of authentication supported and as I assumed you want biometric authentication(not the PIN/Password pattern one) then user cannot have biometrics enrolled without device credentials set. In that case, I would propose asking the user to add these instead of just failing. There you can find an example of how to create an intent for doing it. So these two's I would mark these as incorrect.

    BiometricPrompt.ERROR_NO_SPACE - indicates that there is not enough device storage remaining to complete the operation. It is very highly unlikely to happen but if will happen then your handling is incorrect as triggering the prompt again will most likely result in this error again(if there is no space there is a big chance that it still not be after retrying).

    Also are you sure that if user cancels the operation by himself and you receive the ERROR_USER_CANCELED you want to reshow the prompt? If user canceled it on purpose reshowing it may look very annoying.