PingOne Recognize

Mobile SDK Authentication

Authentication is the biometric equivalent of signing in. During authentication, PingOne Recognize compares the user’s facial biometrics with those computed during enrollment.

If the biometrics match, PingOne Recognize authenticates the user.

Quick Start

Android

val configuration = BiomAuthConfig()

Keyless.authenticate(
    configuration = configuration,
    onCompletion = { result ->
        when (result) {
            is Keyless.KeylessResult.Success -> Log.d("KeylessSDK ", "Authentication success")
            is Keyless.KeylessResult.Failure -> Log.d("KeylessSDK ", "Authentication failure - error code ${result.error.code}")
        }
    }
)

iOS

let configuration = BiomAuthConfig()

Keyless.authenticate(
    configuration: configuration,
    onCompletion: { result in
        switch result {
        case .success(let success):
            print("Authentication success")
        case .failure(let error):
            break
        }
    })

Android 4.6

val configuration = AuthenticationConfiguration.builder.build()

Keyless.authenticate(
    authenticationConfiguration = configuration,
    onCompletion = { result ->
        when (result) {
            is Keyless.KeylessResult.Success -> Log.d("KeylessSDK ", "Authentication success")
            is Keyless.KeylessResult.Failure -> Log.d("KeylessSDK ", "Authentication failure - error code ${result.error.code}")
        }
    }
)

iOS 4.6

let configuration = Keyless.AuthenticationConfiguration.builder.build()

Keyless.authenticate(
    authenticationConfiguration: configuration,
    onCompletion: { result in
        switch result {
        case .success(let success):
            print("Authentication success")
        case .failure(let error):
            break
        }
    })

Flutter

import 'package:keyless_flutter_sdk/keyless.dart';
import 'package:keyless_flutter_sdk/models/configurations/authentication_configuration.dart';

final configuration = BiomAuthConfig();

try {
  final result = await Keyless.instance.authenticate(configuration);
  print("Authentication success");
} catch (error) {
  print("Authentication failure");
}

React Native

import Keyless, { BiomAuthConfig } from '@react-native-keyless/sdk';

const authenticateUser = async () => {
  const configuration = new BiomAuthConfig();

  const result = await Keyless.authenticate(configuration);

  result.fold({
    onSuccess: (data) => {
      console.log('Authentication success', data);
    },
    onFailure: (error) => {
      console.error('Authentication failure:', error);
    },
  });
};

Authentication Configuration

You can configure the authentication process with optional parameters in your BiomAuthConfig() instance or using the builder pattern methods from the AuthenticationConfiguration builder.

Android

public data class BiomAuthConfig(
    public val cameraDelaySeconds: Int = 0,
    public val jwtSigningInfo: JwtSigningInfo?,
    public val livenessConfiguration: LivenessSettings.LivenessConfiguration = LEVEL_1,
    public val livenessEnvironmentAware: Boolean = true,
    public val operationInfo: OperationInfo?,
    public val shouldRemovePin: Boolean = false,
    public val shouldRetrieveSecret: Boolean = false,
    public val shouldDeleteSecret: Boolean = false,
    public val showSuccessFeedback: Boolean = true,
    public val generatingClientState: ClientStateType? = null
)

iOS

public struct BiomAuthConfig: AuthConfig {
    public let cameraDelaySeconds: Int
    public let jwtSigningInfo: JwtSigningInfo?
    public let livenessConfiguration: Keyless.LivenessConfiguration
    public let livenessEnvironmentAware: Bool
    public let operationInfo: Keyless.OperationInfo?
    public let shouldRemovePin: Bool
    public let shouldRetrieveSecret: Bool
    public let shouldDeleteSecret: Bool
    public let showSuccessFeedback: Bool
    public let generatingClientState: ClientStateType?
}

Android 4.6

interface AuthenticationConfigurationBuilder {

    fun retrievingBackup(): AuthenticationConfigurationBuilder
    fun retrievingSecret(): AuthenticationConfigurationBuilder
    fun deletingSecret(): AuthenticationConfigurationBuilder
    fun retrievingTemporaryState(): AuthenticationConfigurationBuilder
    fun withDelay(cameraDelaySeconds: Int): AuthenticationConfigurationBuilder
    fun withLivenessSettings(
        livenessConfiguration: LivenessSettings.LivenessConfiguration,
        livenessTimeout: Int
    ): AuthenticationConfigurationBuilder
    fun withMessageToSign(message: String): AuthenticationConfigurationBuilder
    fun withOperationInfo(
        operationId: String,
        payload: String? = null,
        externalUserId: String? = null
    ): AuthenticationConfigurationBuilder
    fun withPin(pin: String): AuthenticationConfigurationBuilder
    fun withSuccessAnimation(enabled: Boolean = true): AuthenticationConfigurationBuilder
    fun build(): AuthenticationConfiguration
}

iOS 4.6

public class Builder {

    public func retrievingBackup() -> Builder
    public func retrievingSecret() -> Builder
    public func deletingSecret() -> Builder
    public func retrievingTemporaryState() -> Builder
    public func revokingDevice(id: String) -> Builder
    public func withDelay(seconds: Int) -> Builder
    public func withLivenessSettings(
        livenessConfiguration: LivenessConfiguration,
        livenessTimeout: Int
    ) -> Builder
    public func withMessageToSign(_ message: String) -> Builder
    public func withOperationInfo(
        id: String,
        payload: String? = nil,
        externalUserId: String? = nil
    ) -> Builder
    public func withPin(_ pin: String) -> Builder
    public func withSuccessAnimation(_ enabled: Bool) -> Builder
    public func build() -> AuthenticationConfiguration
}

Flutter

class BiomAuthConfig extends AuthConfig {
    final LivenessConfiguration? livenessConfiguration;
    final int? livenessTimeout;
    final int? cameraDelaySeconds;
    final bool? shouldRetrieveTemporaryState;
    final String? b64NewDeviceData;
    final String? b64OldDeviceData;
    final String? deviceToRevoke;
    final bool? shouldRetrieveSecret;
    final bool? shouldRemovePin;
    final JwtSigningInfo? jwtSigningInfo;
    final DynamicLinkingInfo? dynamicLinkingInfo;
    final OperationInfo? operationInfo;
    final bool? showScreenSuccessFlow;
}

React Native

class BiomAuthConfig {
  public readonly shouldRemovePin: boolean;
  public readonly cameraDelaySeconds: number;
  public readonly showSuccessFeedback: boolean;
  public readonly shouldRetrieveSecret: boolean;
  public readonly shouldDeleteSecret: boolean;
  public readonly jwtSigningInfo: JwtSigningInfo | null;
  public readonly dynamicLinkingInfo: DynamicLinkingInfo | null;
  public readonly livenessConfiguration: LivenessConfiguration;
  public readonly livenessEnvironmentAware: boolean;
  public readonly deviceToRevoke: string | null;
  public readonly operationInfo: OperationInfo | null;
  public readonly generatingClientState: ClientStateType | null;
  public readonly shouldRetrieveAuthenticationFrame: boolean | null;
  public readonly presentationStyle: PresentationStyle;
}
The successAnimationEnabled and later showScreenSuccessFlow field has been renamed to showSuccessFeedback, triggering a breaking change. The success animation is now shown by default.

Authentication Success Result

Depending on the configuration options you enable, PingOne Recognize populates the corresponding fields in the AuthenticationSuccess result.

Android

data class AuthenticationSuccess(
      val clientState: String?,
      val secret: KeylessSecret?,
      val secretIDs: Set<KeylessSecret.Identifier>?,
      val signedJwt: String?
) : KeylessSdkSuccess()

iOS

public struct AuthenticationSuccess {
    public let clientState: String?,
    public let secret: KeylessSecret?
    public let secretIDs: Set<KeylessSecret.Identifier>?
    public let signedJwt: String?
}

Flutter

class AuthenticationSuccess {
    final String? customSecret;
    final String? signedJwt;
    final String? temporaryState;
}

React Native

class AuthenticationSuccess {
  customSecret: string | null;
  signedJwt: string | null;
  clientState: string | null;
}

Configuration Options

Backup Data

Backup data is no longer recommended for account recovery and has been removed from Android and iOS SDKs. Use the client state instead. Follow the account recovery guide.

PingOne Recognize can generate backup data that you can use to recover an account.

To create the backup data, use the shouldRetrieveBackup configuration parameter. Once authentication succeeds, copy the backup data from the AuthenticationSuccess result and store it securely.

To recover an account, use the backup parameter during enrollment.

Delaying the PingOne Recognize Evaluation/Decision

By default, there is a two-second delay between the camera preview appearing and liveness evaluation beginning. The cameraDelaySeconds configuration is available to change this delay.

Use careful consideration when implementing this feature for two reasons:
(i) While this allows users to frame themselves, it also gives attackers additional time to optimize their framing.
(ii) Extending the delay increases the "happy path" flow duration. If too long, users may become frustrated and cancel the flow.

Secret management

During authentication, you can create, update, retrieve, and delete secrets, as well as list all stored secret IDs. Use savingSecret, retrievingSecret, deletingSecret, and shouldRetrieveSecretIDs configuration parameters. Retrieved secrets and secret IDs are available in the AuthenticationSuccess response. Learn more in Secret management.

JWT Signing Info

You can specify a payload to be added to a JWT signed by PingOne Recognize with the jwtSigningInfo parameter. See JWT signing for more details.

Liveness Settings

Using livenessConfiguration you can configure the liveness security level during authentication. The possible values are under LivenessSettings.LivenessConfiguration:

DEVELOPMENT
LEVEL_1        // recommended configuration
LEVEL_2

You can also set livenessEnvironmentAware (defaults to true) to help ensure the user is in a suitable setting for verification.

For more details, see the Liveness Settings section.

Operation Info

The operationInfo parameter specifies a customizable unique operation identifier and associated payload stored on the PingOne Recognize backend if authentication succeeds.

Details on how to query stored operations are available in the Operations API.

Client State

Use the generatingClientState parameter of BiomEnrollConfig or BiomAuthConfig to create a client state useful for account recovery.

Camera Preview Customization (BETA)

Use the presentationStyle parameter in BiomAuthConfig to control camera preview behavior during authentication.

  • .cameraPreview (default): Shows the standard live camera preview for user guidance.

  • .noCameraPreview: Hides the camera preview entirely, enabling a faster, minimal interface similar to native biometric flows on mobile devices.

Android 5.2

val configuration = BiomAuthConfig(presentationStyle = PresentationStyle.NO_CAMERA_PREVIEW)
Keyless.authenticate(configuration = configuration, onCompletion = { result ->
    // Handle result
})

iOS 5.2

let configuration = BiomAuthConfig(presentationStyle: .noCameraPreview)
Keyless.authenticate(configuration: configuration, onCompletion: { result in
    // Handle result
})

Flutter

import 'package:keyless_flutter_sdk/keyless.dart';
import 'package:keyless_flutter_sdk/models/configurations/authentication_configuration.dart';

final configuration = BiomAuthConfig(presentationStyle: PresentationStyle.NO_CAMERA_PREVIEW);

try {
  final result = await Keyless.instance.authenticate(configuration);
  print("Authentication success");
} catch (error) {
  print("Authentication failure");
}

React Native

import Keyless, { BiomAuthConfig } from '@react-native-keyless/sdk';

const authenticateUserWithNoCameraPreview = async () => {
  const configuration = new BiomAuthConfig({
      presentationStyle: PresentationStyle.NO_CAMERA_PREVIEW,
    });

  const result = await Keyless.authenticate(configuration);

  result.fold({
    onSuccess: (data) => {
      console.log('Authentication success', data);
    },
    onFailure: (error) => {
      console.error('Authentication failure:', error);
    },
  });
};

For UI customization options for this flow, see UI Customization.