Biometric(Fingerprint) Authentication in a Mendix Native Mobile Application
9 min readFeb 24, 2024
Mendix has a very complete set of modules ready to use. In the Mobile realm, the Native Mobile Resources module is one of the most popular. Besides many features, this module allows us to implement Biometric(Fingerprint) Authentication in a Mendix Native Mobile Application.
Procedure
- [1] In Studio Pro, create a New App using the Blank Native Mobile App template.
- [2] Change the Security Level from Off to Production, in App Security.
- [3] Go to Navigation, in the Native Mobile profile, and define the Role-based home pages as shown below:
- This will instruct Mendix to show the Login page if the user still needs to be authenticated, and if so, for the roles User and Administrator, the default homepage will be Home_Native.
- [4] Open the Home_Native page and drag a Sign-out button from the Toolbox pallet to the empty space at the top right corner of the page.
- [5] Create an entity called Profile with a boolean attribute called IsBiometricAuthEnabled on the Domain Model. In addition, change the Access rules settings as shown below. The XPath constraint
[System.owner='[%CurrentUser%]']
is important to restrict access only to the current user of the application.
- [6] Create a new blank mobile Page called Profile. Use the NativePhone_Default layout.
- [7] Drag a DataView to the Page. Create a Nanoflow DS_Profile that instantiates and returns a new Profile object if not created yet for the current user. Adjust the Security Permissions for this Nanoflow and for the Profile Page: allowed roles User. Use this Nanoflow as the source for the DataView.
- [8] Click on the center of the DataView. Then, using the Connector tab, drag the IsBiometricAuthEnabled attribute to the DataView. The Profile page should be as follows:
- [9] Create a new Nanoflow called
OCH_Profile_IsBiometricAuthEnabledChanged
and define it as the OnChange event of the CheckBox. Adjust the Security user role permissions. Create a Commit activity for the Profile object.
- Also, the Synchronize Activity forces the Profile object to be immediately updated on the Server.
- [10] Once again in the Navigation/Native Mobile profile, create a new item called Profile, in which the target is the Profile page:
- Before running the app for the first time, is important to create a new User account. We could use MxAdmin, however, this user is not associated with the Account entity, so it is not possible to get benefit from the XPath constraint
[System.owner='[%CurrentUser%]']
. We must create a test User for our execution tests. - [11] Create a new page called Login_Web for the Responsive profile using the Login template:
- Define the visibility of this page for the Anonymous user.
- [12] Back to the Navigation, this time using the Responsive Web profile, create a new item called Accounts, defining as target the page Administration.Account_Overview. Also, create an item to Sign Out the application.
- [13] Run the application, proceed with the login using MxAdmin/1 as credentials, and go to the Accounts menu to access the Account Overview page. Create a new user, as shown below:
- After creating the user account, you can log out of the application. We won’t use this Web application anymore.
- [14] Now in your Emulator (or physical device), run the Make it Native 9 app, and configure the runtime URL to your local IP Address. With the application running, after proceeding with the login using the newly created user, in the Profile page, confirm that the value of the boolean IsBiometricAuthEnabled persists if you login/logout repeatedly.
- We reached the point where the Biometric configuration must be done! But first, it’s important to understand how the Biometric Authorization is usually done in the apps.
- Once you enter your credentials for the first time after launching and logging into your app, full synchronization is done between your application and the server. That is, the application has a copy of the database locally on your device that is synced at login.
- At logout, this local database is swapped out of the device, freeing the space occupied by the database. As a side effect, if your database is huge and you are not being selective in your sync strategy, your app may take a long time to start after login, since it performs a full sync.
- To reduce this inconvenience, the idea is never to log out. However, this causes another problem in data-sensitive applications, such as banking and healthcare apps. Such data can be inadvertently seen by someone else with access to your device.
- A pseudo-solution is to proceed with a fake login, that asks for the user credentials when the app is resumed or loaded (considering that the logout wasn’t done earlier).
- Alternatively to this fake login, you can ask for the PIN, the Pattern Lock, or the Biometric Auth, either using the Face ID or the Fingerprint.
- Fortunately, Mendix offers an easy way to implement the Biometric Auth, via Fingerprint, without requiring any extra module or widget from the Marketplace: all you need is the NativeMobileResources (that comes with the Blank Native Mobile App template).
- [15] Create a Nanoflow called SUB_Profile_BiometricAuth. Configure the allowed roles to the User role. Drop an IsBiometricAuthenticationSupported in this Nanoflow. Define the boolean result name as IsBiometricAuthSupported. Use a Decision to check this boolean.
- [16] Retrieve the Profile for the current user. The XPath constraint we’ve defined earlier in the Domain Model helps us here. Then, use a Decision to check if the Profile isn’t empty and the value of the boolean Profile/IsBiometryAuthEnabled. Use the condition:
$Profile != empty
and
$Profile/IsBiometricAuthEnabled = true
- [17] Drag a BiometricAuthentication on the Nanoflow. Define as empty as Reason and the boolean IsAuthenticated as the return value. Use this boolean in a Decision to handle the success of the biometric authentication, or the fail. In case of failure, a message is shown to the user informing that he will have to proceed with the login again. The Nanoflow will resemble the following:
- We need to find a way to catch the OnResume and OnLoad events to fire the Nanoflow we’ve created. For that, we can use the AppEvents widget.
- [18] Drop an AppEvents widget on the Home_Native. We will configure the OnLoad and OnResume events. But first, the Nanoflows must be created.
- [19] Create a Nanoflow called OLO_Profile_BiometricAuth and drop a Clear Cached Session Data (more on this later) and a Synchronize Everything activities. In addition, drag the SUB_Profile_BiometricAuth on it.
- [20] Create a Nanoflow called ORE_Profile_BiometricAuth and drop a Synchronize Everything activity and the SUB_Profile_BiometricAuth on it.
- In the AppEvents widget, configure the OnLoad and OnResume as shown in the image:
- To test if the Biometric Authentication is working properly, your Device or Emulator should be configured to allow the usage of Fingerprint to unlock the screen. Such configuration varies from device to device and therefore is beyond the scope of this article. For Samsung devices, see How to set Fingerprint Lock on my Samsung Device.
- [21] Considering that your device is configured correctly, let’s run the application on your Device/Emulator via Make it Native 9 and provide the credentials to log in. Then, go to the Profile page and turn on the Is biometric auth enabled option.
- [22] Now minimize the Make in Native 9 and resume the app again (OnResume event). It should ask you for the biometry unlocks via fingerprint. Repeat the process, but instead, swipe out the application from the recent apps list. Open the app again (OnLoad event), and the biometric unlock should be required.
- Theoretically, the proposed solution seems to be working fine… Or not?!
Problems
- No, this is not working fine, unfortunately! The main issue I faced was the proliferation of sessions during my tests. At every attempt to (re)load the app again, a new Session was created with previous Profile data (
IsAuthenticatedAuthEnabled == false
), and therefore the Fingerprint Lock protection auth was not fired. - Remember that there’s a limit of 5 simultaneous sessions in the trial license, considering that we are using the local deployment, causing the issue below:
- Call the Clear Cached Session Data and Synchronize activities in the OnLoad event nanoflow didn’t solve the issue, since many sessions could still be created.
- Only after a while, the oldest sessions are freed.
- Another issue is related to the period between consecutive resume or load events. It may be requested by the business rule that, within 30-second intervals (for example), the Biometric Authorization is not required.
- To handle this issue, it was required to change the SUB_Profile_BiometricAuth nanoflow as shown below:
- Two new nanoflows were created: SUB_WasRecentLogin and SUB_StoreLastUserLoginDateTime.
- The idea is to save the last login time in the local storage, and before proceeding with the Biometric Auth, check if the limit of 30 seconds from the current time has been exceeded. If so, a new Biometric Auth will be required.
Conclusion & Comments
- The usage of Biometric Auth (in this case using Fingerprint) is very beneficial to the user since it provides a fast way to unlock access to the app;
- Avoiding the signout can save some sync time considering that the local database will be preserved according to the strategy defined in the Navigation/Native Profile. It is also useful for offline applications
- Unfortunately, the proposed solution didn’t solve 100% this issue, due to the sessions proliferation at each onLoad event. Therefore, this article is indeed a support request to the Mendix Community to improve the code to properly handle the issues related to the proliferation of sessions.
Source Code
You are welcome to clone this project and file any issues or solutions!