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?
}
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.