Authenticate user with fingerprint
Introduction
Fingerprint authentication allows users to perform biometric authentication by the use of Android's Fingerprint API introduced in Android Marshmallow (6.0). The biggest gain of enabling Fingerprint Authentication is the improved end-users experience. Users are now enabled to access their sensitive data or authenticate transactions using Android's common fingerprint validation.
The SDK allows you to authenticate users with the fingerprint scanner (if available on the device). You can use it for both regular authentication as well as mobile authentication. Users will be able to scan their fingerprint as many times as the Android system will allow them to. If Android fingerprint API will return an error for any reason (for example when too many failed attempts was detected), the SDK will revoke fingerprint authentication and perform a fallback to PIN authentication.
Fingerprint security
The fingerprint data is stored on a device securely and should never leave a device. Google has very strict guidelines for device manufacturers about how fingerprint data should be stored and handled on the device:
- Capturing and recognizing your fingerprint must happen in a secure part of the device hardware known as a Trusted Execution Environment (TEE). Hardware access must be limited to the TEE and protected by an SELinux policy.
- Fingerprint data must be secured within sensor hardware or trusted memory so that images of your fingerprint are inaccessible.
- Only the encrypted form of the fingerprint data can be stored on the file system, even if the file system itself is encrypted.
- Fingerprint data must be removed from the device when a user is removed.
- Rooting of a device must not compromise fingerprint data.
However, there are a couple of things, that you should keep in mind when using fingerprint authentication:
- Using the fingerprint may be less secure than a strong PIN because with fingerprint authentication the actual authentication step is performed solely on the mobile device, whereas the PIN authentication is done server side.
- The Android OS assumes that all fingerprints registered on a device belong to the same person. If this is not the case (for example a parent and a child have both registered their fingerprints on the same device) then the SDK cannot distinguish whether the parent or the child performed fingerprint authentication.
- A physical copy of your fingerprint could be used to unlock your phone. You leave fingerprints on many things you touch, including your phone.
Availability
A User can enable fingerprint authentication only if all of the following requirements are met:
- the device is running Android Marshmallow (6.0, API Level 23) or greater
- the device is not rooted
- the device has hardware fingerprint reader
- the user has already registered at least one fingerprint
- the client configuration on the Token Server allows use of fingerprint authentication
Root detection
The root detection check is applied during the fingerprint authentication, even if root detection is disabled for the application itself. The reason is that rooted devices are more vulnerable, as the application sandbox as well as AndroidKeystore can be violated. The situation is even more serious for clients who are not using tampering protection.
Fingerprint changes
As explained in google docs keys stored in the AndroidKeyStore will become permanently invalidated once a new fingerprint is enrolled or all fingerprints are disenrolled. In such case, the SDK will deregister fingerprint authenticator and the user will have to enroll for fingerprint authentication again.
Using fingerprint authentication with multiple user profiles
The Android SDK v5.03.00 introduced support for multiple user profiles. When this feature is implemented by you, an end-user will be able to create and use different accounts (profiles) on the same device. Each profile has it's own separated PIN, push notification support and other features. However, as stated above the Android Fingerprint API was designed with the assumption that a device is being used by only one person. This person can register multiple fingerprints, but from the API perspective they all belong to the same person. In particular, if a device is being shared between multiple people and all of them will register one or more fingerprints, the API is not able to distinguish whom of them performed authentication.
Because of this, if the application supports both the multiple profiles feature and fingerprint authentication, you should keep in mind, that it has some (potential) drawbacks. Let's assume that Bob is the owner of a device, but he shares it with his wife Alice. They have both registered their fingerprints and they both created profile in the ExampleApp.
- When the ExampleApp asks Bob for a fingerprint for login or to confirm a transaction, any valid (registered) fingerprint will be accepted. Because of that Alice can login to Bob's account using her fingerprint.
- When Bob tries to authenticate with a fingerprint but the exceeds number of failed attempts, the Android Fingerprint API can be blocked automatically for some amount of time (around 15-30 seconds). If Alice will try to log in to her account shortly after that, she might not be able to do so before the API will be unblocked.
- When the Token Server detects improper usage of a fingerprint refresh token that indicates a corrupted or modified fingerprint keystore - all fingerprint refresh tokens on this device will be revoked on the server side.
Authenticate using Fingerprint Authentication
Whenever fingerprint authentication is enabled and the device is not rooted the user will be prompt to scan his/her finger instead of providing his/her PIN in order to authenticate. The SDK will use OneginiFingerprintAuthenticationRequestHandler
interface to ask for a fingerprint. The handler should show a view that includes a common Android's fingerprint icon.
Due to the fact that fingerprint scanning is not perfect (e.g. the user may have wet or dirty hands, also the temperature may impact the scan result) the user can always choose to fallback on PIN authentication. This can be done by calling OneginiFingerprintCallback#fallbackToPin()
method.
Also, after failing to scan a fingerprint for the allowed number of times, the SDK will automatically fallback on the PIN authentication method. If the user will not be able to provide a valid PIN within the allowed number of times, he will be deregistered.
Enabling fingerprint authentication
In order to enable fingerprint authentication for user you need to request a list of not yet registered authenticators with UserClient.getNotRegisteredAuthenticators(final UserProfile userProfile)
. This method can be used after user is authenticated and will return a set of OneginiAuthenticator
that are possible to register. Then you can register chosen authenticator providing the authenticator's instance to UserClient.registerAuthenticator(final OneginiAuthenticator authenticator, final OneginiAuthenticatorRegistrationHandler handler)
method, along with the handler that will inform you about success or failure of the registration process. If your device haven't met one of the requirements, the fingerprint authenticator won't be present on the list of authenticators.
Disabling Fingerprint Authentication
To disable fingerprint authentication for currently authenticated user profile call disableFingerprintAuthentication()
on the UserClient
instance. The method will revoke user's fingerprint refresh token on both client and server side. User will still be able to login using his PIN.
Example code for registering a fingerprint authenticator
Note that registering a new authenticator doesn't make it a preferred authenticator to be used. By default preferred authenticator is PIN, so if you want to
change it, you need to inform the SDK about it with UserClient.setPreferredAuthenticator(final OneginiAuthenticator auth)
providing any registered
authenticator.
Please note that CustomInfo is an optional param that will be always null during fingerprint authenticator registration.
Authentication handlers
The SDK provides two interfaces (OneginiFingerprintAuthenticationRequestHandler
and OneginiMobileAuthWithPushFingerprintRequestHandler
for
respectively: regular and push authentication) that you can implement in your application to use the fingerprint authentication. Later you will need to provide
them to OneginiClientBuilder
instance as shown below:
Example code for supplying fingerprint auth request handlers to the SDK
OneginiFingerprintAuthenticationRequestHandler
interface exposes four methods you should use to control the process of scanning the fingerprint and informing
the end user about the progress:
startAuthentication(final UserProfile userProfile, final OneginiFingerprintCallback callback)
triggered when a new fingerprint authentication request is made, providing anUserProfile
object and a fingerprint callback;onNextAuthenticationAttempt()
called when user provided incorrect fingerprint but still haven't reach the failed attempts limit,onFingerprintCaptured()
invoked when user scanned his fingerprint and the fingerprint validation is performed. That's a good moment to show an update on the UI informing user about received attempt,finishAuthentication()
triggered when fingerprint scanning finished either with success or an error.
OneginiMobileAuthWithPushFingerprintRequestHandler
works in exactly the same manner with a single change in parameters of startAuthentication()
method,
where instead of the UserProfile
you get the OneginiMobileAuthenticationRequest
object containing information about the push request as well as UserProfile
. You can
read more about mobile fingerprint authentication in mobile authentication topic guide.
Example code for OneginiFingerprintAuthenticationRequestHandler implementation
To control the flow of fingerprint authentication you should use provided OneginiFingerprintCallback
callback. It consists of three methods:
acceptAuthenticationRequest()
that should be called when user accepts fingerprint authentication request,denyAuthenticationRequest
which should be triggered when user denies the fingerprint authentication request, which can be done by calling theOneginiFingerprintCallback#denyAuthenticationRequest
method.fallbackToPin
that should be invoked when user decides to resign from fingerprint authentication and wants to enter his PIN to finish authentication.
In the example code above you should use the static instance of OneginiFingerprintCallback
in the FingerprintActivity
to react on user actions.