Enhance Your Biometric Login Security with Flutter — Protect Your App from Hackers!

Amorn Apichattanakul
KBTG Life
Published in
7 min readMay 17, 2023

--

Dash is locked!!!

Biometric authentication is a popular method, and is commonly used by many apps for login purposes. It provides a great user experience by allowing users to access their app without having to memorize all of their passwords or PINs — they just need their face or fingerprint. In this article, I would like to explore how we can enhance the security of biometric login to prevent simple attacks such as listening for a true/false flag and granting access to hackers who want to exploit vulnerabilities in the system. If you are a Flutter developer who has implemented biometric login in your app, it’s important to carefully consider the security implications and review the suggestions presented in this article.

First, let me refer to this article describing how to hack biometric login in iOS:

Essentially, it’s the same in Android and Flutter. You can simply inject a script to fake the flag to true, and that’s pretty much it. However, this poses a significant security risk as your credit card and other sensitive information in the app can be easily exploited by hackers. If they can bypass your pin code from the OS and gain access to the app, they could potentially steal your information.

Here’s the thing; if your app does not require any sensitive information from the user, it may not be necessary to implement this additional security measure. In such cases, it may be sufficient to rely on the biometric authentication feature provided by the platform. However, if you are interested in learning how to enhance the security of biometric login in your app, feel free to continue reading.

I won’t go into the details on how to implement a simple biometric login, as there are many articles available on this topic. Instead, I will mainly focus on how to implement extra security measures to ensure that even if a hacker is able to fake the flag, they cannot gain further access.

The basic idea of our implementation is this; The biometric authentication is just a trigger to initiate the next action, but it does not provide immediate access to the main part of the app. With biometric login, you can obtain an access token, but note that this access token should be restricted to the non-financial part of the app only. This is because biometric authentication is not as secure as PIN authentication, and therefore may not be trusted for financial transactions.

Even with biometric authentication, it is still necessary to use a PIN to confirm the user’s identity. It’s important to ensure that the PIN is secure and not stored on the user’s device. This way, even if the device is stolen, the thief cannot bypass the PIN and gain access to the financial part of the app without the actual PIN. While biometric authentication can provide a convenient way for users to access their app, a PIN is still considered more secure as it provides an additional layer of security.

Let’s start step by step

First of all, we need to check whether the user’s device supports biometric login. If the device does not support biometric login or if the user has not enabled it, we need to handle this situation appropriately.

Android has a concept of Weak/Strong biometric authentication, which is described in the link below:

While Android has a concept of Weak/Strong biometric authentication, iOS does not provide this distinction. In iOS, biometric authentication is provided as a single authentication option that is either enabled or disabled.

In Android, fingerprint authentication is generally considered a strong form of biometric authentication, while facial recognition and iris scanning are considered weaker forms of biometric authentication. However, this may not always be the case and depends on how the Android Compatibility Definition Document (CDD) evaluates biometric authentication methods. The definitions of Strong and Weak authentication can be found in this link:

When I talked to the Penetration Test team, they told me they don’t have a preference whether we use strong or both types of biometric authentication. This is because they don’t fully trust biometric authentication methods. It’s up to us whether we want to implement strong authentication only or both types. However, keep in mind that normal users may not fully understand the distinction between strong and weak authentication methods. For example, if a device only supports fingerprint authentication but not facial recognition, users may not understand why the option for facial recognition is unavailable.

For biometric authentication in Flutter, I use the local_auth library, which is available on pub.dev

This library supports both weak and strong forms of biometric authentication, allowing you to choose which method to use based on your app’s requirements.

The second step is to consider using a biometric storage concept, which is a secure storage that can only be accessed after biometric authentication to improve security. This allows us to save sensitive data, such as a key, to the storage. iOS provides this functionality through the ‘Keychain’ feature, which can be accessed using Face ID or Touch ID, as described in the link below:

Android also provides a similar functionality through the ‘Android Keystore System’, which can be used to store cryptographic keys securely and accessed through biometric authentication, as described here:

In terms of security, it’s important to assume that the client, or mobile application, can be compromised and therefore cannot be fully trusted. This means that even if the client sends a request for biometric authentication, we cannot allow it to proceed in the normal way 😆 Additional security measures, such as server-side authentication, may be required to ensure that the biometric authentication process is performed securely. And yes, to ensure the security of biometric authentication, it’s important to have a backend system and cryptography to help handle it.

Thirdly, once the client decides to use biometric authentication, the client will create a private key with a key pair. To generate the key pair securely, we can use the ‘cryptography’ library available on pub.dev

Next, we generate a public key and seed from the private key, and send them to the server for handshaking. The server will then send us the server key, which we can use for future authentication and data exchange.

Once we receive the server key from the server, we can use it in combination with our private key to create a shared key between the client and server. This shared key can be used to encrypt and decrypt data sent between the client and server

Finally, we save the shared key into our biometric storage for future use. This concept is similar to the handshake process described in my previous article. Be sure to check out if you haven’t here:

However, the last step will be different in that we will save the shared key into the biometric storage instead of the secure storage.

Once you have obtained your biometric key, you can use it in your next login. The steps involved in the login process will be as follows:

  1. Ask for biometric authentication from the user
  2. Retrieve the shared key from the biometric storage
  3. Receive a string from the server, which we call the challengeString
  4. Use the challengeString to encrypt the shared key, resulting in an encrypted shared key that we call encryptShareKey
  5. Send the bodyKey obtained from the handshake process, along with the encrypted shared key (encryptShareKey), to the server to obtain an accessToken

The accessToken obtained from the server can be used as a biometric token. However, its usage can be restricted based on specific requirements. For instance, it can be used to log in and view information, but not for making a money transfer. When it is necessary to perform a money transfer, the biometric token needs to be upgraded to a different token that requires a PIN for additional security. This upgraded token can be called the pinToken.

It may seem complex, but to help users understand the concept step by step, I have created a sample project with detailed explanations in the code. The project is available on my GitHub repository.

This should cover most aspects of biometric login, but you need to handle some additional cases, such as removing, adding, or re-adding a fingerprint or face. Your app must detect these cases and remove the biometric token stored inside it, considering any changes to the fingerprint or face as belonging to a new user. Otherwise, a hacker could add their own fingerprint to a user’s device and gain access to the application.

That’s essentially everything you need to know to implement secure biometric login. This concept has been passed penetration testing, so you can follow my guidelines to make your app secure with biometric authentication. By doing so, you will close another potential security gap in your app.

Congratulations! There will be no more true/false flag issues

Want to read more stories like this? Or catch up with the latest trends in the technology world? Be sure to check out our website for more at www.kbtg.tech

--

--

Amorn Apichattanakul
KBTG Life

Google Developer Expert for Flutter & Dart | Senior Flutter/iOS Software Engineer @ KBTG