- a mobile app typically runs on a personal device, making the user and device coincide;
- a mobile app allows for much more possibilities in terms of local storage and using the device’s security features.
Users only see the tip of the iceberg of the authentication process. Namely, whenever they are asked to:
- enter some information (e.g., username, PIN, password, OTP),
- perform biometric verification (e.g., fingerprint, faceID),
- confirm an action.
All the real complexity, such as cryptography and protocols, are hidden from the user.
Regarding the user experience, the key questions are how and how often (when) a user should authenticate. On the one hand, all user interactions create friction, so reducing the number of interactions is generally good for the user experience. On the other hand, long lasting sessions (where no user interaction is required) are a potential security disaster and might leave some of your users wondering if your mobile app is secure (e.g., when their phone is left unattended, will someone else be able to use the mobile app?).
The answer is thus not straightforward and highly depends on the value and risk associated with the usage of the mobile app. What kind of data is processed and can be accessed? What is the risk of unauthorized data access, the ability to approve transactions or the ability to sign documents? Should locally stored data be protected?
Interplay between user authentication and app authentication
The mobile app will need to authenticate to the back-end system in some way. But how exactly does this relate to user authentication and app authentication?
On one end of the spectrum user authentication and app authentication are decoupled. The user authenticates first, after which the app is ready for use. All subsequent business logic request to the backend server rely on app authentication. On the other end of the spectrum, user authentication and app authentication coincide, i.e. every time the app needs to authenticate, the user will interact.
Clearly some trade-off is required between both extremes, as security requirements often mandate some level of user interaction (within a certain time frame), but without overdoing it and constantly asking the user to authenticate.
Mobile app authentication best practices
Embedding stardard web authentication
Probably one of the worst strategies is to embed the standard username-password website authentication flow into the mobile app. Entering a (complex) password on a smartphone is challenging.
Given the user friction the above strategy will cause, a quick fix is to store the username-password in the app or in the mobile OS’s secure storage. However, for authenticating to the backend, the password must be available to the mobile app. This creates a clear risk for passwords to be stolen on the mobile device. To mitigate this risk, tokens are used. However, in practice, the security risk often remains the same. Read more about it in our next blog post.
When 2 Factor Authentication (2FA) is required, standard web authentication often relies on OTPs that are used on top of username-password. OTPs typically consist of 6 digits arriving in an SMS or being generated with Google Authenticator or similar apps. However, on a mobile device, this is a recipe for disaster, as users have to switch between apps to copy the OTP.
Retrofitting legacy authentication technology
Several attempts have been made to retrofit legacy authentication technology into mobile apps, often masquerading poor security with modern, fancy smartphone features.
For example, you can use biometrics to unlock access to a stored password/token. From the users’ perspective, he will be performing an easy biometric authentication, but underneath, security remains extremely poor, as the password/token still needs to be sent over to the server.
One of the worst things you can do with biometrics for security purposes, is using a simple yes/no biometric query. The mobile device returns yes/no to the app depending on the success of the biometric authentication. This is totally useless as anyone capable of swapping the value (e.g., by patching the app code or hooking on these systems calls) can bypass the security check entirely.
As a second example, protocols such as OCRA are aimed at automating the generation and transfer of an OTP, without any user interaction. The clear advantage is that they’re not based on presenting a plaintext password/token to a server to authenticate, but rather on using a cryptographic key – that remains secret – to compute an OTP. Still, authentication remains poor as security is limited by the number of digits of the OTP. This is especially dangerous when the OTP becomes the only authentication factor.
Fully using the device capabilities with sensible fallbacks
Nearly all modern smartphones are shipped with a secure element capable of securely storing cryptographic keys. The secure element will not allow reading the key, but only performing certain operations with it, such as putting a digital signature. The keys can be unlocked in a multitude of ways, ranging from always-on, using the screen lock or with the biometric sensors of the device.
TLS with mutual authentication (mTLS) exists for over two decades, but was never able to really break through. This is mainly due to the non-existing to poor browser integration for managing the client private keys. We now have devices capable of performing digital signatures and securely storing private keys, making them the perfect tools to perform a mutually authenticated protocol, such as mTLS or SIGMA-I.
In cases where user interaction is required, but it is not possible to use the biometric capabilities of the device (i.e., defective sensor or personal injury), a fallback scenario is required. Given the limited input capabilities of a smartphone, PIN codes are obvious candidates, but they come with important caveats. Sending a PIN code to the server for verification is a dangerous approach.
Apart from the risks associated with the secure transport, the server needs to store the PIN in plain* for comparison. Local verification of a PIN is also a bad idea, as it will open the door for brute forcing on the device, as there are no hardware security measures blocking the user from trying too many times. What you really need is a verification-without-disclosure approach, where the server validates the PIN, without ever seeing it (e.g. nextAuth’s True 2FA technology).
Based on the issues discussed in this article, it is clear that mobile app authentication should meet the following criteria:
- Avoid local-only validation on the mobile device of biometrics or user secrets.
- Fully use the capabilities of the built-in secure element.
- Use digital signatures. Do not rely on long-term secrets (i.e. tokens or passwords) that are sent in plaintext to the server for verification.
- Ask explicit user approval when necessary, based on the security requirements of the application.
- Connect user and app authentication, manage app sessions and user interaction requirements explicitly.
- Use verification-without-disclosure technology to validate fallback PIN codes or passwords.
Did this article spark your interest in better user and app authentication? Learn more about the nextAuth approach and get deep technical insights.
* The best practice ‘hashing and salting’ approach for passwords, does not offer additional protection in practice. A typical PIN is only 4 to 6 digits, which takes milliseconds to brute-force (hash and salt all possible values until there is a match). Storing PIN codes inside a Hardware Secure Module (HSM) server-side does solve the issue of secure storage. However, this is a costly option and an attacker with access to the server might still be able to learn the PIN code by querying the HSM for every possible PIN until it verifies.