DeviceAuthentication external object - Draft

Unofficial Content

Current Status

This feature is currently supported in iOS only. Android support is coming soon.

This document is a draft and may change in the future.

Introduction

All mobile platforms(1) provide the means for locally authenticating the device's user.

In some cases, the local authentication is provided by biometrics sensors (face or fingerprint recognition, retina scans, etc.). In some other cases a PIN, password or pattern is used.

The biometrics method used may vary depending on the platform or the device: iPhones, from iPhone 5 up to iPhone 8 Plus have a fingerprint sensor, iPhone X has face recognition, Android devices may have a fingerprint sensor.

However, the objective is always the same: to make sure that the person using the application is the device's owner.

GeneXus provides an API to make it easy for the developer to use these "local authentication" methods, regardless of the platform or the device.

Scenarios

The main scenario we want to solve is being able to check that the person using the application is the owner of the device.

Going into more detail, these use cases could be solved using device authentication mechanisms:

  • Allow the user to show sensitive information, for example, health information stored in the device.
  • Allow the user to interact with sensitive information in the device, for example, transferring money to a third party.
  • Remember user's credentials to authenticate with another system, for example, an application that uses GAM may ask the user if they want to remember the user name and password information, and may ask the user for the fingerprint or another Local Authentication mechanism to securely store the information provided by the user.

DeviceAuthentication external object

In GeneXus, there is a new External Object, part of the Core Module, named GeneXus.SD.DeviceAuthentication.

Domains

DeviceAuthenticationPolicy

The enumerated domain that indicates the type of device authentication to be used.

Valid values are:

  • Biometrics
  • Any (meaning biometrics or password)

This enumerated domain is used in the external object's methods.

Properties

BiometricsDescription: String

Returns the name of the biometrics authentication method available on the current device.

For iOS, the possible values are "Touch ID", "Face ID" or the empty value if the property IsAvailable returns False.

Discussion:

According to Apple's Human Interface Guidelines, the application should always "Reference authentication methods accurately", and explains furthermore:

Don't reference Touch ID on a device that supports Face ID. Conversely, don't reference Face ID on a device that supports Touch ID. Check the device's capabilities and use the appropriate terminology.

This property lets the developer use the appropriate term whenever they need to provide a description. For example, adding a button caption that may read "Authenticate with Touch ID" or "Authenticate with Face ID" depending on the device's capabilities.

AllowableReuseDuration: Numeric

Indicates the minimum time before asking the user to local authenticate again after a successful authentication.

This property is read/write.

Default value: zero.

Discussion:

There are situations where the user may be asked several times to authenticate, to access different sections of the application.

To avoid asking the user to authenticate each time, a "reuse duration" may be specified. If set, then the user is considered authenticated if the time elapsed since the last authentication is less that the allowed reuse duration.

To reset the setting and ask the user immediately to authenticate, a value of zero must be specified.

Methods

IsAvailable(method: DeviceAuthenticationPolicy): Boolean

Returns True if the API can be used in the current device, False otherwise.

There may be several reasons why the API cannot be used:

  • The device does not have the required hardware (fingerprint sensor, face recognition camera, etc.),
  • The OS version does not support the feature (Android prior to version 6.0)
  • The user decided not to use the security mechanisms (e.g., in iOS the user may turn off the fingerprint sensor)

The method parameter specifies the policy the developer wants to use. If it is set to Biometrics, then only platforms/devices that support biometrics and have them enabled by the end user will return True. If set to Any, it will return True if biometrics are supported or if the device has a password.

Authenticate(method: DeviceAuthenticationPolicy, usageDescription: String): Boolean

This method performs the authentication step, using the method that corresponds to the current device.

If the method parameter is set to Biometrics, then only biometrics sensors will be used. If set to Any and biometrics is not available or is disabled, then the password will be used.

It returns True if the user could be authenticated otherwise, it returns False. In particular, if the property IsAvailable has value False, the return value of this method is also False.

Calling the method without using the return value (assigning it to a variable, checking it in an if command, etc.) will make the Composite block containing the call to fail.

The usageDescription parameter is used to present the end user with a message when they are prompted for the local authorization. It cannot be empty in iOS.

Examples:

Event 'AuthenticateLocalUser'
    composite
        &auth = DeviceAuthentication.Authenticate(DeviceAuthenticationPolicy.Biometrics, "Please authenticate")
        if (&auth)
            // user authenticated
        else
            // error condition
        endif
    endComposite
EndEvent

In the previous example, the result is assigned to a variable and then checked in an if command.

In the following example, if the user cannot be authenticated, the message is never shown because the event is canceled upon authentication failure.

Event 'AuthenticateLocalUser'
    composite
        DeviceAuthentication.Authenticate(DeviceAuthenticationPolicy.Any, "Please authenticate")
        msg('User is valid!')
    endComposite
EndEvent

Solving the proposed scenarios

1. Allow the user to show sensitive information

The following code could be used to restrict access to a given Panel:

Event ClientStart
    Composite
        &Policy = DeviceAuthenticationPolicy.Any
        &Available = DeviceAuthentication.IsAvailable(&Policy)
        if &Available
            &Authenticated = DeviceAuthentication.Authenticate(&Policy, "Please authenticate")
            if not &Authenticated
                Actions.Cancel()
            endif
        endif
    EndComposite
EndEvent

2. Allow the user to interact with sensitive information in the device

This scenario is similar to the first one, but could also be used in any user event.

Event 'ButtonTapped'
    Composite
        &Policy = DeviceAuthenticationPolicy.Biometrics 
        &Available = DeviceAuthentication.IsAvailable(&Policy)
        if &Available
            DeviceAuthentication.Authenticate(&Policy, "Please authenticate")
        endif
        PerformSensitiveOperation() 
    EndComposite
EndEvent

3. Remember user's credentials

What we want in this case, is to remember the user name and password after a successful login, so that the user will not have to type them again.

Event 'Login'
    Composite
        Actions.Login(&user, &pass)
        if DeviceAuthentication.IsAvailable(DeviceAuthenticationPolicy.Biometrics)
            Confirm('Do you want to use biometrics to log in in the future?')
            DeviceAuthentication.Authenticate(DeviceAuthenticationPolicy.Biometrics, "Please authenticate to store your credentials")
            ClientStorage.SetSecure(!'user_name', &user)
            ClientStorage.SetSecure(!'user_pass', &pass)
        endif
    EndComposite
EndEvent

And to log in without asking for the credentials to the user:

Event ClientStart
    Composite
        if DeviceAuthentication.IsAvailable(DeviceAuthenticationPolicy.Biometrics)
            DeviceAuthentication.Authenticate(DeviceAuthenticationPolicy.Biometrics, "Please authenticate to log in")
            &user = ClientStorage.Get(!'user_name')
            &pass = ClientStorage.Get(!'user_pass')
            Actions.Login(&user, &pass)
            Return
        endif
    EndComposite
EndEvent

Warning: This approach works, but has a problem: the user credentials are not stored with the biometrics information. If the user turns off biometrics, the credentials are still there. They could also be accessed even if the user is not prompted to authenticate..


(1) Android (6.0 and above) and iOS at the time of this writing.