Biometric authentication is familiar to all of you. Fingerprint login, FaceId payment and other requirement scenarios are now common. Therefore, Android, iOS, RN and Flutter are all involved in this business scenario.

Of course, the difference may lie in your familiarity with platform capabilities or interface capabilities. Therefore, this article mainly introduces what you need to pay attention to when using biometric authentication on Android and iOS, what the specific process is, and gives you a summary of information that you need or will need.

⚠️ Note: this article is more inclined to the Angle of research information, suitable for the need to access or in the access process of the direction of questions, rather than API use tutorial, in addition to a long warning ~

First of all, let’s talk about a concept that everyone knows, which is that no matter Android or iOS, no matter fingerprint or FaceId, as long as you use the API provided by the system, as a developer, you can’t get any biometric data of the user, so simply you can only call the system API. And then you get success or failure.

A, the Android

The history of biometric authentication on Android has been pretty bumpy, with two simple phases:

  • FingerprintManager (API 23)
  • BiometricPrompt28 (API)

So as you can see in the figure below, there are actually two underlying services that support API capabilities for biometric authentication, but it’s worth noting that FingerprintManager has been added with the @deprecated flag in Api28 (Android P). Included androidx compatibility pack FingerprintManagerCompat also marked the @ Deprecated, because the official offer more fool, more out-of-the-box androidx. Biometrics. BiometricPrompt.

1.1. Use BiometricPrompt

For a brief introduction to accessing BiometricPrompt, the first step is to add permissions


<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.test.biometric">
    <uses-permission android:name="android.permission.USE_BIOMETRIC" />
    <uses-permission android:name="android.permission.USE_FINGERPRINT" />

</manifest>
Copy the code

Then call BiometricPrompt to build system pop-up box information, the specific content can be seen in the following figure:

It is best to set AuthenticationCallback and call Authenticate, then wait for the authorization result to enter the successful callback:

    biometricPrompt = new BiometricPrompt(activity, uiThreadExecutor, authenticationCallback);
    biometricPrompt.authenticate(promptInfo);
Copy the code

Of course, the above code is missing a lot of details:

  • For example, it needs to be FragmentActivity;

  • Does the detection device support biometric authentication (or not now?)? ;

  • Determine which biometric authentication is supported. Of course, by default BiometricPrompt will handle this for you, and if there are more than one, it will pop up a selection.

If the authentication fails, the corresponding error code can be obtained in onAuthenticationError:

onAuthenticationError Type
BIOMETRIC_ERROR_LOCKOUT The operation is cancelled because the API is locked due to too many attempts (usually once)authenticateFor example, the fingerprint did not pass many times, lock, but can be called later)
BIOMETRIC_ERROR_LOCKOUT_PERMANENT Because the BIOMETRIC_ERROR_LOCKOUT occurs so many times that the operation is cancelled, this is a true LOCK.
BIOMETRIC_ERROR_NO_SPACE The remaining storage space is insufficient
BIOMETRIC_ERROR_TIMEOUT timeout
BIOMETRIC_ERROR_UNABLE_TO_PROCESS The sensor is abnormal or cannot process the current information
BIOMETRIC_ERROR_USER_CANCELED The user cancels the operation
BIOMETRIC_ERROR_NO_BIOMETRIC The user does not register any biometrics with the device
BIOMETRIC_ERROR_CANCELED The operation was cancelled because the biosensor was not available
BIOMETRIC_ERROR_HW_NOT_PRESENT The device has no biometric sensors
BIOMETRIC_ERROR_HW_UNAVAILABLE The device hardware is unavailable
BIOMETRIC_ERROR_VENDOR If there are situations that are not listed above, Other

1.2 BiometricPrompt customization

After simply accessing BiometricPrompt, you might wonder: BiometricPrompt is convenient, but the UI is a bit ugly. Can you customize it?

Sorry, no. Yes, BiometricPrompt doesn’t allow you to customize the UI, even if you want to change the color. If you look at the Biometric source code, you will see that there is no official plan for customization, unless you CV the code and build one yourself. My personal guess is that one of them is an under-screen fingerprint.

Migrating from FingerprintManager to BiometricPrompt also says: dump fingerprint layout files because you won’t need them anymore. The AndroidX biometric library comes with a standardized UI.

What is a standardized UI? Here are three phones using the BiometricPrompt, as you can see:

  • The first and the second were basically the same, except for a slight difference in position;
  • The third mobile phone is the fingerprint under the screen, you can see that the UI effect of the whole fingerprint input is completely another style of the manufacturer;

So with BiometricPrompt you don’t need to pay attention to the UI, because you have no choice. You don’t even need to pay attention to the security of biometric authentication type on the phone, because both CDD and UI will be implemented directly by OEM. For example, Samsung’s UI is as shown below:

Android compatibility definition document describes the biometric authentication in the CDD (Android) _ sensor the strength of the degree of safety, and at the framework level BiometricFragment and FingerprintDialogFragment are @ hide, You simply go even androidx. Biometric: biometric. Aar library, you don’t see BiometricFragment layout, can only see FingerprintDialogFragment layout.

So there’s no way to customize the UI? There are two options:

  • Continue to use FingerprintManager. Although deprecated, it is still available and will work on Android 11. Here’s a comparison of FingerprintManager and BiometricPrompt on the same phone on Android 11:

  • Use Tencent’s Soter, which we’ll talk about later;

1.3、Login + BiometricPrompt

After introducing the call and UI, we will talk about BiometricPrompt in combination with the Login scenario. The official provides a Demo for the Login scenario, which mainly introduces the whole business process. The specific code can be seen in the official BiometricLoginKotlin. As mentioned above, BiometricPrompt only provides authentication results. Combined with the Login service, BiometricPrompt is mainly used for authentication and encryption in the official example:

As shown in the figure above, after login, we obtained the user’s Token information. This Token information may be the content merged by the server based on the user’s password, so it contains some sensitive privacy. For security, we cannot store it directly during the period. Instead, BiometricPrompt is used to implement post-encrypted storage:

  • First of all byKeyStore, mainly to get a password containingSecretKeyOf course, there is a key operation here, that issetUserAuthenticationRequired(true), we will explain later;
  • Then useSecretKeycreateClipherClipherAn object commonly used for encryption and decryption in Java;
  • usingBiometricPrompt.CryptoObject(cipher)To invoke biometric authorization;
  • You get one when you have a successful authorizationAuthenticationResult, Result contains the key informationcryptoObject? .ciphercipher.ivEncrypted offset vector;
  • After the successful use of authorizationcryptoObject? .cipherEncrypt the Token, and thencipher.ivSave together toSharePerferences, is completed based onBiometricPromptEncryption save;

Do you feel a little confused? To put it simply: we encrypt the Token with a key that only the user is authorized to use if authenticated, so that the Token is safe for us whether it is leaked or not.

Then in the KeyStore logic here is a setUserAuthenticationRequired (true), the meaning of this operation is: if the user only through authentication are authorized to use this key, namely when set to true:

The user must authenticate to the Android device by using a subset of his screen lock credentials, such as password /PIN/ pattern or biometrics, to authorize the use of the key.

That is, the key can be generated only when the security lock screen is set. Once the security lock screen is disabled (reconfigured to none, no authentication mode, and forcibly reset), the key will be irreversibly invalid.

Can also set the setUserAuthenticationValidityDurationSeconds to request key must be at least one biological feature is only available, and once it is set to true, if the user has registered a new biological characteristic, it will be irrevocably failure.

Therefore, it can be seen that in this process, the key is bound with the system security, so that there is no fear of information leakage such as Token. Also, the successful authorization of CryptoObject is integrated with the KeyStore, which can resist attacks such as root more effectively.

Conversely, the acquisition process is similar, as shown in the figure below:

  • inSharePerferencesTo obtain the encrypted Token and IV information;
  • Again usingSecretKeycreateClipher, but this time bring the iv information saved;
  • usingBiometricPrompt.CryptoObject(cipher)To invoke biometric authorization;
  • After authorization succeedscryptoObject? .cipherThe Token is encrypted to obtain the original Token information.

So you can see that the basic idea is to get CryptoObject with BiometricPrompt authentication, right? Cipher to decrypt, through the security level of the system to protect our privacy information.

A BiometricPrompt includes auth-per-use and time-bound:

  • auth-per-useKey requirements Each time a key is used, authentication must be performed, which we passed earlierBiometricPrompt.CryptoObject(cipher)Calling authorization methods is one such implementation;
  • time-boundA key is a key that is valid for a certain period of time and can passsetUserAuthenticationValidityDurationSecondsSet the duration. If you set it to a very short time, say 5 seconds, it behaves almost like auth-per-use.

See the official Biometric authentication-on-Android for more information

1.4, Tencent soter

As mentioned above, There is soter on Android. Tencent abstracts its process into a complete biometric standard: SOTER on the basis of the whole process of wechat fingerprint payment.

SOTER will cooperate with phone makers, on interface to system’s original ability to provide safe, has nothing to do with business of security domain (TEE, is independent of the mobile phone operating system safety area, root or escape can’t access to the application (TA) development difficulty and adaptation to reduce costs, do it even if the external environment is not credible, can still security authorization.

The Trusted Execution Environment (TEE) is an independent security zone that runs independently from the mobile operating system. In SOTER, all sensitive operations such as key generation, data signature processing, fingerprint verification, and sensitive data transmission are performed in TEE. Equipment used and SOTER root keys by the manufacturer on the production line burn-in, fundamentally solve the problem of the root key credibility, and root keys for trust chain, derived keys, and complete, all handset vendors will cooperate with WeChat TEE with hardware, and through the tencent security platform and WeChat payment security team acceptance, accord with standard of SOTER.

In short, this is a third-party library that supports pass-through vendors and has background service docking verification. It is still being updated in the last 5 months, so what’s wrong with it?

That is, all mobile phone manufacturers and models cooperating with wechat can be used normally, and strange problems often appear on some manufacturers’ systems, such as:

  • The MiUI13 binding service is abnormal.
  • Hongmeng SYSTEM API level error reported;
  • An inexplicable breakdown;

But it can achieve basically similar capabilities to wechat pay, so how to choose depends on your business needs.

The supported models can be checked: # How many devices already support Tceh-SOter

iOS

Biometric authentication on iOS is relatively comfortable. Compared to fingerprint, Face, and Iris, which need to distinguish between system version and manufacturer, face ID and Touch ID on iOS are very unified and simple.

To use biometric authentication on iOS, you need to add the description to the info.plist file:

<key>NSFaceIDUsageDescription</key>
<string>Why is my app authenticating using face id?</string>
Copy the code

Then import the header file # import < LocalAuthentication/LocalAuthentication. H >, finally create LAContext authorized to execute the operation, there is also simple to show the corresponding error code:

Error Code Type
LAErrorSystemCancel The system cancels authorization, for example, there is another APP switch
LAErrorUserCancel User authentication disabled
LAErrorAuthenticationFailed Authorization failure
LAErrorPasscodeNotSet No password is set
LAErrorBiometryNotAvailable ID is not available, for example, not open
LAErrorBiometryNotEnrolled The ID is not available and the user is not entered
LAErrorUserFallback The user chooses to enter a password

In terms of custom UI, we all know that there is no custom UI for iOS biometric authentication, nor does it support custom UI. The system is what it is, and you can only configure actions like ‘whether to allow password authorization’.

At this point I believe Android developers are very envious of iOS, there is a problem is a system problem, can not be fixed.

Similarly, a brief description of the Login scenario flow using biometrics on iOS:

  • After obtaining the Token information, verify the user’s TouchID/FaceID;
  • After the authentication succeeds, the Token information is saved to the keychain (a keychain is only a data store for storing sensitive data such as passwords and certificates).
  • After the save, verify TouchID/FaceID to obtain the corresponding information at the next login.

There are two key points:

  • Level of access: for example, whether authentication is required every time to access the project;
  • Level of authentication: the circumstances under which stored information can be accessed;

Access, for example, keychain is first need to create the accessControl, generally can be created through SecAccessControlCreateWithFlags accessControl, here is a key parameter is used to specify the access level:

  • KSecAttrAccessibleAfterFirstUnlock boot after the key is not available, need to wait for the user to enter the password
  • KSecAttrAccessibleAfterFirstUnlockThisDeviceOnly: boot after the key is not available, need to wait for the user input password, but limited to the current equipment
  • KSecAttrAccessibleWhenUnlocked: unlock the device key state will remain available
  • KSecAttrAccessibleWhenUnlockedThisDeviceOnly: unlock the device key will remain available, only the current equipment
  • KSecAttrAccessibleWhenPasscodeSetThisDeviceOnly: unlock the device key will remain available, only after the user password key is available
  • KSecAttrAccessibleAlways: always available and has been Deprecated
  • KSecAttrAccessibleAlwaysThisDeviceOnly: key available all the time, but cannot be migrated to other devices, has been Deprecated

Similar scenarios generally use kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, plus SecAccessControlCreateFlags logo, it is mainly used to specify the hope users in the access key string constraints, Generally, userPresence is used in similar scenarios:

  • DevicePasscode: Restricts password access
  • BiometryAny: Access with any registered Touch or Face ID
  • BiometryCurrentSet: Restricts access using current registered Touch or Face ID
  • UserPresence: Restrict biometric or password access
  • Watch: Access using a watch

KSecAttrAccessControl = kSecAttrAccessControl = kSecAttrAccessControl = kSecClass = kSecClass KSecClassGenericPassword:

  • KSecClassGenericPassword: general password
  • KSecClassInternetPassword: Internet password
  • Certificate of kSecClassCertificate:
  • KSecClassKey: encryption key
  • KSecClassIdentity: indicates the identity authentication

Of course, do you notice at this point that accessControl and keychain are not mentionedLAContext

Actually there is a corresponding when creating the accessControl kSecUseAuthenticationContext parameter is used to set LAContext to keychain certification, but also can not set, specific as follows:

  • If not specified and the project requires authentication, a new one is automatically createdLAContext Discard after using once.
  • If you are using a previously authenticatedLAContext , the operation succeeds directly without requiring user authentication;
  • If you are using a previously unauthenticatedLAContext , the system tries to run theLAContext If successful, it can be reused in subsequent keystring operations.

More visible: accessing_keychain_ITEMS_with_face_ID_or_touch_id

As you can see, on iOS you can simply configure it, because the system level doesn’t give you extra power.

Three, the last

Although this article does not teach you how to use Android or iOS biometric authentication from the beginning, as a summary, this article basically covers the basic concepts and issues related to Android or iOS biometric authentication. I believe this article will be especially suitable for those who are investigating the development of biometric authentication.

Finally, as usual, if you have any questions or suggestions about this convenience, feel free to leave a comment.