Protection Policy

View this page for | |

The protection policy defines the protection requirements for a provisioned object (Transaction Signing Key, Session Transport Key, or OTP Key).

The PolicyType values are:

  • DEVICE – the object is protected against cloning (that is, it cannot be used outside the mobile device).
  • PASSWORD – the object is also protected by an end-user password.
  • BIOPASSWORD – same as Password but with additional support for an alternative biometric authentication (for example, fingerprint/face/iris) on a hardware-capable device.

For further details, see:

ActivID AS push solution customization

ActivID Appliance push solution customization

HID Authentication Service push solution customization

PasswordPolicy

This policy defines the constraints on the password protecting the object:

  • Minlength – Minimum password length
  • Maxlength – Maximum password length
  • Additional restrictions for alphanumeric format:
    • Min Number of UpperCase letters
    • Min Number of LowerCase letters
    • Min Number of Alpha characters
    • Min Number of Numeric characters
    • Min Number of Non-Alphanumeric characters
    • Maximum Number of UpperCase letters
    • Maximum Number of LowerCase letters
    • Maximum Number of Alpha characters
    • Maximum Number of Numeric characters
    • Maximum Number of Non-Alphanumeric characters
    • Allow/prohibit sequential characters
  • History restriction parameters:
    • maxHistory – number of unique new passwords that have to be associated with the key before an old password can be reused. 0 authorizes users to reuse current password when password is changed. This value is set by the server.

    • minAge – period of time (in days) that a password must be used before the user can change it. It must be less than the maximum password age. 0 allow changes immediately. This value is set by the server.

    • maxAge – period of time (in days) users can keep a password before they have to change it. 0 means password never expires. This value is set by the server.

  • Caching parameters:

    • CacheEnabled - flag indicating if the password cache is enabled

    • CacheTimeout - period of time (in seconds) during which with password is stored in the cache (by default, 30 seconds)

Note:  
  • When defining the rules of the password policy, make sure that there are no logical conflicts. For example, do not specify that the minimum number of numeric characters is 8, in combination a maximum password length of 6 characters.

  • When not set, the maximum values are equal to the maximum length defined for the password.

Authenticating with Password

For further details about each specific API call, refer to the API references.

Using a PIN or Numeric Password

You can define an exclusive numeric (PIN) policy which is more user-friendly in mobile authentication deployments.

As an example, the following parameters can be used to set a numeric-only policy for a 6 to 10-character password length:

  • MinLength = 6
  • MaxLength = 10
  • MinNumeric = 6
  • MaxNumeric = 10
  • maxUpperCase = 0
  • maxLowerCase = 0
  • maxAlpha = 0
  • maxNonAlpha = 0

In the server configuration, this would be defined with the following key protection policy parameters:

UP=0;LOW=0;NUM=6;ALPHA=0;NALPHA=0;MUP=0;MLOW=0;MNUM=8;MALPHA=0;MNALPHA=0;MINLEN=6;MAXLEN=8

For further details, see:

ActivID AS Key Protection Policy Parameters

ActivID Appliance Key Protection Policy Parameters

HID Authentication Service Key Protection Policy Parameters

Enabling Password Caching

The SDK provides password caching support for the transaction signing operation (Transaction.setStatus). When enabled, the signing password can be cached for the specified cache timeout period or until used.

To implement password caching in an integrating application when using a password policy:

  1. Retrieve the protection policy information PasswordPolicy.isCacheEnabled.

If yes:

  1. Use the PasswordPolicy.verifyPassword method to validate the password and store it for the PasswordPolicy.getCacheTimeout period (by default, 30 seconds).

  2. To sign the transaction, use the Transaction.setStatus method as usual but thesigningPassword parameter can be omitted (it will retrieve the password value from cache).

BioPasswordPolicy – Authentication with Biometrics (Fingerprint/Facial/Iris)

Biometric authentication is a convenient alternative to password authentication for end users.

Importantly, it does not replace the password as users can fallback to password authentication at any time.

In that perspective, provisioning for biometric authentication is the same as Container Provisioning. The user must provide the password during the container creation.

  • Server-side – the policy to configure at container or key level is ‘biometricorpassword’
  • Client-side – the policy protecting the keys is represented by BioPasswordPolicy, extending PasswordPolicy.
Note: If the user’s device does not have a fingerprint sensor (or the manufacturer does not support the authorized Biometrics class level), then the policy is represented by PasswordPolicy.

For further details, see:

ActivID AS Key Protection Policy Parameters

ActivID Appliance Key Protection Policy Parameters

HID Authentication Service Key Protection Policy Parameters

Supported Biometric Authenticators

By default, the HID Approve SDK is designed with enforced security requirements strictly authorizing devices with Class 3 (Strong) biometric sensors.

The Android Compatibility Definition Document (CDD) defines two class levels of biometric strength that can be used by the device manufacturer to certify the device biometric sensor. Each class has a set of prerequisites, privileges, and constraints which are assigned based on the presence of a secure pipeline and the three acceptance rates:

  • Spoof Acceptance Rate (SAR)

  • False Acceptance Rate (FAR)

  • False Rejection Rate (FRR)

Authenticator Metrics Constraints
BIOMETRIC_STRONG (Class 3)
  • SAR - 0-7%

  • FAR - 1/50k

  • FRR - 10%

  • Strict hardware sensor security strength requirements

  • 72 hours before fallback to primary authentication (such as PIN, pattern, or password)

  • Direct integration with hardware-backed keystore

(Default and recommended configuration)

BIOMETRIC_WEAK (Class 2)
  • SAR - 7-20%

  • FAR - 1/50k

  • FRR - 10%

  • Supports a greater number of device and biometry form factors

  • 24 hours before fallback to primary authentication

  • No direct integration with hardware-backed keystore

To provide a concrete example, most fingerprint authentication sensors are certified as Class 3 (Strong) but facial recognition sensors are often certified as Class 2 (weak) but can vary depending on manufacturer and device capabilities.

An integrator can widen security restrictions to authorize the use of biometric class 2 (weak) authenticators by adding an authentication rule to the device policy rules.

Enabling Authentication with Fingerprint/Face/Iris

By default, biometric authentication is not enabled. That means that BioPasswordPolicy, acts exactly as PasswordPolicy until it is explicitly enabled.

The authentication state can be discovered using BioPasswordPolicy.getBioAuthenticationState. It returns one of the BioAuthenticationState values:

  • ENABLED – biometric authentication is enabled, the SDK will accept password null in authentication methods
  • NOT_ENABLED – biometric authentication is not enabled

    To enable, a call to BioPasswordPolicy.enableBioAuthentication is required.

  • NOT_CAPABLE – the device does not have a biometric sensor so biometric authentication is not possible
  • NOT_ENROLLED – the user has not enrolled biometric features at the device level so biometric authentication cannot be enabled
  • INVALID_KEY – biometric authentication has been invalidated by the platform following an update to system enrolled biometric data

    To re-enable, a call to BioPasswordPolicy.enableBioAuthentication is required

The minimum authorized biometric authenticator, either BIOMETRIC_STRONG (Class 3) or BIOMETRIC_WEAK (Class 2 and Class 3), can be discovered using BioPasswordPolicy.getAuthorizedAuthenticator().

To enable biometric authentication, the app calls BioPasswordPolicy.enableBioAuthentication as illustrated below.

Sample Enabling Biometric Authentication on Android

Copy
// You can check the policy protecting the container, or alternatively a policy protecting a key.
    // Unless a specific configuration is used, they will be the same.
    var containerPolicy: ProtectionPolicy? = null
    try {
        containerPolicy = myContainer.protectionPolicy
    } catch (e: UnsupportedDeviceException) {
        e.printStackTrace()
    } catch (e: InternalException) {
        e.printStackTrace()
    } catch (e: LostCredentialsException) {
        e.printStackTrace()
    }
    // Identify the protection policy with the type BIOPASSWORD
    if (containerPolicy!!.type == ProtectionPolicy.PolicyType.BIOPASSWORD.toString()) {
        // The BIOPASSWORD policy enables you to rely on the biometric API of the device
        // The first step is to enable the usage of the biometric API in replacement of the password.
        val bioPasswordPolicy = containerPolicy as BioPasswordPolicy?
        try {
            if (bioPasswordPolicy!!.bioAuthenticationState == BioAuthenticationState.NOT_ENABLED || bioPasswordPolicy!!.bioAuthenticationState == BioAuthenticationState.INVALID_KEY) {
                // You need to prompt the user for his/her password
                // Then enable authentication with fingerprint
                val userPassword = "userPassword".toCharArray()
                bioPasswordPolicy.enableBioAuthentication(userPassword)
            }
        } catch (e: InternalException) {
            e.printStackTrace()
        } catch (e: UnsupportedDeviceException) {
            e.printStackTrace()
        } catch (e: LostCredentialsException) {
            e.printStackTrace()
        } catch (e: AuthenticationException) {
            e.printStackTrace()
        } catch (e: FingerprintNotEnrolledException) { // The user has not enrolled its biometric data in the device.
            e.printStackTrace()
        } catch (e: FingerprintAuthenticationRequiredException) { //Authentication with fingerprint is required to perform the operation.
            e.printStackTrace()
        } catch (e: PasswordExpiredException) { // !!!  PasswordExpiredException if expired password is given (changePassword required). !!!
            e.printStackTrace()
        }
    }
Copy
// You can check the policy protecting the container, or alternatively a policy protecting a key.
    // Unless a specific configuration is used, they will be the same.
    ProtectionPolicy containerPolicy = null;
    try {
        containerPolicy = myContainer.getProtectionPolicy();
    } catch (UnsupportedDeviceException | InternalException | LostCredentialsException e) {
        e.printStackTrace();
    }
    
    // Identify the protection policy with the type BIOPASSWORD
    if (containerPolicy.getType().equals(ProtectionPolicy.PolicyType.BIOPASSWORD.toString())) {

        // The BIOPASSWORD policy enables you to rely on the biometric API of the device
        // The first step is to enable the usage of the biometric API in replacement of the password.
        BioPasswordPolicy bioPasswordPolicy = (BioPasswordPolicy) containerPolicy;
        try {
            if (bioPasswordPolicy.getBioAuthenticationState() == BioAuthenticationState.NOT_ENABLED || bioPasswordPolicy.getBioAuthenticationState() == BioAuthenticationState.INVALID_KEY) {
                // You need to prompt the user for his/her password
                // Then enable authentication with fingerprint
                char[] userPassword = "userPassword".toCharArray();
                bioPasswordPolicy.enableBioAuthentication(userPassword);
            }
        } catch (InternalException | UnsupportedDeviceException | LostCredentialsException | AuthenticationException e) {
            e.printStackTrace();
        } catch (FingerprintNotEnrolledException e) { // The user has not enrolled its biometric data in the device.
            e.printStackTrace();
        } catch (FingerprintAuthenticationRequiredException e) { //Authentication with fingerprint is required to perform the operation.
            e.printStackTrace();
        } catch (PasswordExpiredException e) { // !!!  PasswordExpiredException if expired password is given (changePassword required). !!!
            e.printStackTrace();
        }
    }

Authenticating with Fingerprint/Face/Iris

Regardless of the operation to perform (transaction signing, OTP generation…), if the key is protected by BioPasswordPolicy, (Key.getProtectionPolicy) and fingerprint authentication is enabled (BioPasswordPolicy.getBioAuthenticationState and BioPasswordPolicy.enableBioAuthentication), then the app does not have to prompt the end user for their password. Instead, the app calls the SDK methods, passing null value as the password.

The behavior depends on the platform.

The SDK leverages the Android Biometrics Jetpack Library (androidx.biometric API). The framework handles the UI display for the app and notifies fingerprint or biometric sensor events through a callback for all Android 6.0 (API level 23) devices and later. Refer to the Android documentation for details.

Before performing the intended operation, the app needs to pass the objects listed below to the HID Approve SDK using setBiometricPrompt:

Then, the app calls the SDK method, passing null value as the password.

During this operation, the Android platform biometrics framework is triggered to display a dialog using the provided PromptInfo and invoke the provided AuthenticationCallback delegate asynchronously for any additional handling of sensor events.

For example :

  • If authentication is successfully matched, the method proceeds by invoking the onAuthenticationSucceeded callback

  • If authentication match is locked by the system (for example, due to consecutive failures), the method returns the FingerprintAuthenticationRequiredException error and also invokes the callback onAuthenticationError with the ERROR_LOCKOUT error code

  • If the end user cancels the dialog, the method returns the FingerprintAuthenticationRequiredException error and also invokes the callback onAuthenticationError with ERROR_CANCELED error code

An integrating application can then choose to fallback to PIN/password mode upon failure.

The resetBiometricPrompt method will release objects stored during the setBiometricPrompt method call. This method should be called when the app wants to disable SDK biometric support.

The following sample illustrates the required calls (for readability, the snippet does not include problems related to UI refresh):

Sample Fingerprint Authentication on Android

Copy
// You need to define and registered the callback for the biometric authentication
    // https://developer.android.com/reference/androidx/biometric/BiometricPrompt.AuthenticationCallback
    val customAuthenticationCallback: BiometricPrompt.AuthenticationCallback =
        object : BiometricPrompt.AuthenticationCallback() {
            override fun onAuthenticationFailed() {
                // The biometric data provided are incorrect
            }

            override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
                //Called when an unrecoverable error has been encountered and authentication has stopped.
            }

            override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
                // The biometric data provided are correct
            }
        }
    if (customAuthenticationCallback != null) {
        // You can check the policy protecting the container, or alternatively a policy protecting a key.
        // Unless a specific configuration is used, they will be the same.
        var protectionPolicy: ProtectionPolicy? = null
        try {
            protectionPolicy = myContainer.protectionPolicy
        } catch (e: UnsupportedDeviceException) {
            e.printStackTrace()
        } catch (e: InternalException) {
            e.printStackTrace()
        } catch (e: LostCredentialsException) {
            e.printStackTrace()
        }
        if (protectionPolicy is BioPasswordPolicy) {
            // You need to configure the prompt that will be displayed to the user
            // https://developer.android.com/reference/androidx/biometric/BiometricPrompt.PromptInfo
            val promptInfo = PromptInfo.Builder()
                .setTitle("Confirm fingerprint to continue")
                .setNegativeButtonText("Cancel")
                .build()
            // Provide the activity or fragment you will associate with the prompt
            protectionPolicy.setBiometricPrompt(
                myActivity,
                customAuthenticationCallback,
                promptInfo
            )
        }
    }
    // ............
    // You can now perform the requested operation without providing password.
    // you will be prompted by the promptInfo you defined earlier
    // Authentication error will be handle by customAuthenticationCallback
    // For example getOTP :
    try {
        val otp = otpGenerator!!.getOTP(null)
    } catch (e: AuthenticationException) {
        e.printStackTrace()
    } catch (e: InternalException) {
        e.printStackTrace()
    } catch (e: PasswordExpiredException) {
        e.printStackTrace()
    } catch (e: FingerprintAuthenticationRequiredException) {
        e.printStackTrace()
    } catch (e: PasswordRequiredException) {
        e.printStackTrace()
    }
Copy
// You need to define and registered the callback for the biometric authentication
    // https://developer.android.com/reference/androidx/biometric/BiometricPrompt.AuthenticationCallback

    BiometricPrompt.AuthenticationCallback customAuthenticationCallback = new BiometricPrompt.AuthenticationCallback() {
        @Override
        public void onAuthenticationFailed() {
            // The biometric data provided are incorrect
        }
        @Override
        public void onAuthenticationError(int errorCode, CharSequence errString) {
            //Called when an unrecoverable error has been encountered and authentication has stopped.
        }

        @Override
        public void onAuthenticationSucceeded(BiometricPrompt.AuthenticationResult result) {
            // The biometric data provided are correct
        }
    };


    if (customAuthenticationCallback != null) {
        // You can check the policy protecting the container, or alternatively a policy protecting a key.
        // Unless a specific configuration is used, they will be the same.
        ProtectionPolicy protectionPolicy = null;
        try {
            protectionPolicy = myContainer.getProtectionPolicy();
        } catch (UnsupportedDeviceException e) {
            e.printStackTrace();
        } catch (InternalException e) {
            e.printStackTrace();
        } catch (LostCredentialsException e) {
            e.printStackTrace();
        }
        if (protectionPolicy instanceof BioPasswordPolicy) {
            // You need to configure the prompt that will be displayed to the user
            // https://developer.android.com/reference/androidx/biometric/BiometricPrompt.PromptInfo
            androidx.biometric.BiometricPrompt.PromptInfo promptInfo =
                    new androidx.biometric.BiometricPrompt.PromptInfo.Builder()
                            .setTitle("Confirm fingerprint to continue")
                            .setNegativeButtonText("Cancel")
                            .build();
            // Provide the activity or fragment you will associate with the prompt
            ((BioPasswordPolicy) protectionPolicy).setBiometricPrompt( myActivity , customAuthenticationCallback, promptInfo );
        }
    }
    // ------
    // You can now perform the requested operation without providing password.
    // you will be prompted by the promptInfo you defined earlier
    // For example getOTP :
    try {
        char[] otp = otpGenerator.getOTP(null);
    } catch (AuthenticationException e) {
        e.printStackTrace();
    } catch (InternalException e) {
        e.printStackTrace();
    } catch (PasswordExpiredException e) {
        e.printStackTrace();
    } catch (FingerprintAuthenticationRequiredException e) {
        e.printStackTrace();
    } catch (PasswordRequiredException e) {
        e.printStackTrace();
    }

For further details, see:

ActivID AS Key Protection Policy Parameters

ActivID Appliance Key Protection Policy Parameters

HID Authentication Service Key Protection Policy Parameters

Lock Policy

The following sections define the LockType type and parameters for the password and lock.

Type

  • NONE – password never locks.
  • LOCK – password locks after maximum counter value is reached.
  • DELAY – an exponential delay is inserted between each failed authentication attempt.

Parameters

For further details, see:

ActivID AS Key Protection Policy Parameters

ActivID Appliance Key Protection Policy Parameters

HID Authentication Service Key Protection Policy Parameters