GaitAuth™ Authentication

Note: The authenticator functionality outlined on this page is currently in experimental beta and the interface to this portion of the SDK may change over time. Current support is for iOS, with Android coming soon.

Using GaitAuth Authenticator objects, you can automatically collect gait features, score those features, apply authentication logic to the scores, and produce an authenticated, unauthenticated, or inconclusive authentication status.

Authentication configurations are a customizable set of rules that take inputs (like feature scores) and produce an authentication result.

Creating an Authenticator

Before you begin, make sure you’ve set up the SDK and loaded a trained model.

An Authenticator instance collects data from the device and allows you to query the authentication status at any time. To create a new authenticator, you’ll want to provide a configuration that determines the authentication behavior:

Android

    double QUANTILE_THRESHOLD = 0.8; // your desire quantile threshold
    GaitQuantileConfig config = new GaitQuantileConfig(QUANTILE_THRESHOLD);
    authenticator = GaitAuth.getInstance().createAuthenticator(config, model);

iOS

let authenticator = unifyId.gaitAuth.authenticator(
  config: GaitQuantileConfig(
    ...
  ),
  model: model
)

When an authenticator is created, depending on its configuration, certain processes may begin. For example:

  1. A gait-based configuration causes feature collection to automatically begin, removing the need to explicitly call startFeatureUpdates.
  2. A configuration that uses the device unlock status may begin listening for lock/unlock events.

Authentication Status

The current authentication status can be queried with the status function. A completion handler should be provided to process the authentication result.

Android

authenticator.getStatus(new AuthenticationListener() {
    @Override
    public void onComplete(AuthenticationResult authenticationResult) {
        // Authentication status obtained
    }

    @Override
    public void onFailure(GaitAuthException e) {
        // Failure to querying authentication status
    }
});

iOS

authenticator.status { result in
    switch result {
    case .success(let authenticationResult: AuthenticationResult):
        // Authentication status obtained
    case .failure(let error: GaitAuthError):
        // Failure querying authentication status
    }
}

A result of .success does not necessarily mean that the user should be authenticated. It means that querying for the status was successful. To see the actual authentication result, check authenticationResult.status, and it should be one of .authenticated, .unauthenticated, or .inconclusive.

In addition to status, each successful authentication result also has an authenticationResult.context property which provides additional information about the authentication decision. Depending on the configuration being used, different context values are provided.

The status can be queried multiple times for an authenticator, and as long as the authenticator instance is allocated it will continue any processes it has begun (e.g., collecting features or listening for unlock events). To stop these processes, ensure there are no more references to it so it will be de-allocated.

Configurations

Authenticators use configurations, which define the rules for determining authentication status. Configurations can expose options to customize their behavior. Additionally, based on the inputs/signals a configuration uses, an authenticator that uses it may begin certain data collection processes.

Currently, a gait-based quantile configuration and a device authentication configuration are available in the SDK. As new configurations are added, they will be documented below.

Gait Quantile Config

The Gait Quantile Config takes recent feature scores and returns an authenticated result if splitting the features across numQuantiles quantiles, all data at or above the nth (n = quantile) quantile are at or above the score threshold (threshold). A few examples:

  • numQuantiles: 100, quantile: 75, threshold: 0.5
    The result is authenticated if the top 25% of scores are at or above 0.5.
  • numQuantiles: 100, quantile: 20, threshold: 0.5
    The result is authenticated if the top 80% of scores are at or above 0.5.
  • numQuantiles: 5, quantile: 2, threshold: 0.8
    The result is authenticated if the top 60% of scores are at or above 0.8.

Create the Authenticator

To create an authenticator with the quantile configuration, provide a GaitQuantileConfig and a trained model.

The configuration has the following options:

  • minNumScores
    Minimum number of scores to require. Otherwise, inconclusive will be returned as the result.
  • maxNumScores
    Maximum number of scores to use, ordered by most recent. Additional scores are not used.
  • maxScoreAge
    Maximum allowed age for scores, in seconds. Scores older than this limit are not used.
  • numQuantiles
    Number of quantiles.
  • quantile
    Quantile number to require.
  • threshold
    Score threshold to require.

Because a model is needed to score features, a trained/downloaded model is also required. Your complete call will look something like this:

Android
double QUANTILE_THRESHOLD = 0.8;
GaitQuantileConfig config = new GaitQuantileConfig(QUANTILE_THRESHOLD);
config.setMinNumScores(5);
config.setMaxNumScores(50);
config.setMaxScoreAge(300);
config.setNumQuantiles(100);
config.setQuantile(50);
Authenticator authenticator = GaitAuth.getInstance().createAuthenticator(config, gaitModel);
iOS
let authenticator = unifyId.gaitAuth.authenticator(
  config: GaitQuantileConfig(
    minScores: 5,
    maxScores: 50,
    maxScoreAge: 300,
    numQuantiles: 100,
    quantile: 50,
    threshold: 0.8,
  ),
  model: model
)

Feature Collection

When an authenticator is created with a GaitQuantileConfig, feature collection begins, and the features are stored locally in a buffer. Calling status on the authenticator queries the features in this buffer. No separate call to startFeatureUpdates is required.

To stop feature collection, ensure there are no more references to the authenticator instance so that it will be de-allocated.

Context

Along with a status, authentication results also contain a context property.

Android

In Android, for authenticators created with a GaitQuantileConfig, the context is Map<String, Object> with the following values:

Map<String, Object> context = result.getContext();
// Get Number of features collected and scores
int featureCount = (int) context.get("featuresCount");
// Get list of GaitScore objects
List<GaitScore> scores = (List<GaitScore>) context.get("featureScores");
// Get string explanation for non-authenticated results
if (context.containsKey("reason")) {
    String reason = (String) context.get("reason");
}
iOS

In iOS, for authenticators created with a GaitQuantileConfig, the context is a dictionary with the following values:

[
  "featuresCount": ...,     // Number of features collected and scored
  "featureScores": [...],   // Array of GaitScore objects
  "reason": ...   // String explanation for non-authenticated results
]

The featuresCount value represents the number of features scored and used to produce the authentication result. Features older than maxScoreAge or beyond maxScores are not included in this count. featureScores is the array (with length featuresCount) of GaitScore objects, each of which includes a date and value for each feature.

The reason value is present only when the authentication result is unauthenticated or inconclusive.

Device Authentication Config

The Device Authentication Config produces the following behavior:

  • authenticated if the device is currently, or has recently been, unlocked
  • unauthenticated if the device is currently locked or has not recently been unlocked
  • inconclusive if a determination cannot be made

Depending on the maxUnlockAge option, the authenticator either looks at the current state or uses a lookback window.

Create the Authenticator

To create an authenticator with the device authentication configuration, provide a DeviceAuthenticationConfig. Unlike the quantile configuration, no model is provided because device authentication does not require it.

The configuration has a single option:

  • maxUnlockAge
    How far back, in seconds, to detect an unlock. If no value is provided, the default behavior is to only consider the current locked/unlocked state. Using a value of 60 would allow the authenticator to return authenticated if the device is currently locked, but was unlocked within the last minute.

To create an authenticator that considers only the current state:

Android
long MAX_LOCK_AGE = 60000; // your desire max lock age
DeviceAuthenticationConfig config = new DeviceAuthenticationConfig(MAX_LOCK_AGE);
try {
    Authenticator authenticator = GaitAuth.getInstance().createAuthenticator(config);
} catch (GaitAuthException e) {
    // Failure to create Authenticator with the provided DeviceAuthenticatorConfig
}
iOS
let authenticator = unifyId.gaitAuth.authenticator(
  config: DeviceAuthenticationConfig()
)

Context

Android

In Android, for authenticators created with a DeviceAuthenticationConfig, the context is a Map<String, Object> with the following values:

// Get most recent unlock method
String lastUnlockMethod = (String) context.get("lastUnlockMethod");
// Get most recent unlock date
String lastUnlockDate = (String) context.get("lastUnlockDate");
// Get current lock/unlock state of device
String unlockState = (String) context.get("unlockState");
// Get string explanation for non-authenticated results
if (context.containsKey("reason")) {
    String reason = (String) context.get("reason");
}
iOS

In iOS, for authenticators created with a DeviceAuthenticationConfig, the context is a dictionary with the following values:

[
  "lastUnlockMethod": ...,  // Most recent unlock method
  "lastUnlockDate": ...,    // Most recent unlock date
  "unlockState": ...,       // Current lock/unlock state of device
  "reason": ...   // String explanation for non-authenticated results
]

The lastUnlockMethod is one of passcode, fingerprint, face, or unknown, and describes how the phone was most recently unlocked. It does not necessarily mean that the phone is currently unlocked. The lastUnlockDate is the corresponding unlock time.

The unlockState represents the current unlock state of the device and is one of locked, unlocked, or unknown.

The reason value is present only when the authentication result is unauthenticated or inconclusive.

Updated: