---
title: Mobile SDK Authentication
description: Learn how to authenticate users with the PingOne Recognize Mobile SDK.
component: recognize
page_id: recognize:mobile-sdk:mobile-sdk-authentication
canonical_url: https://docs.pingidentity.com/recognize/mobile-sdk/mobile-sdk-authentication.html
llms_txt: https://docs.pingidentity.com/recognize/llms.txt
docs_for_agents: https://developer.pingidentity.com/build-with-ai/docs-for-agents.md
revdate: April 20, 2026
section_ids:
  quick-start: Quick Start
  android: Android
  ios: iOS
  android-4-6: Android 4.6
  ios-4-6: iOS 4.6
  flutter: Flutter
  react-native: React Native
  authentication-configuration: Authentication Configuration
  android-2: Android
  ios-2: iOS
  android-4-6-2: Android 4.6
  ios-4-6-2: iOS 4.6
  flutter-2: Flutter
  react-native-2: React Native
  authentication-success-result: Authentication Success Result
  android-3: Android
  ios-3: iOS
  flutter-3: Flutter
  react-native-3: React Native
  configuration-options: Configuration Options
  backup-data: Backup Data
  delaying-the-pingone-recognize-evaluationdecision: Delaying the PingOne Recognize Evaluation/Decision
  secret-management: Secret management
  jwt-signing-info: JWT Signing Info
  liveness-settings: Liveness Settings
  operation-info: Operation Info
  client-state: Client State
  camera-preview-customization-beta: Camera Preview Customization (BETA)
  android-5-2: Android 5.2
  ios-5-2: iOS 5.2
  flutter-4: Flutter
  react-native-4: React Native
---

# 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](mobile-sdk-enrollment.html).

If the biometrics match, PingOne Recognize authenticates the user.

## Quick Start

### Android

```kotlin
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

```swift
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

```kotlin
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

```swift
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

```dart
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

```javascript
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

```kotlin
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

```swift
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

```kotlin
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

```swift
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

```dart
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

```typescript
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

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

### iOS

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

### Flutter

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

### React Native

```javascript
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](mobile-sdk-account-recovery.html) 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](mobile-sdk-secret-management.html).

### 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](mobile-sdk-jwt-signing.html) for more details.

### Liveness Settings

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

```none
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](mobile-sdk-liveness-settings.html) 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](https://docs.keyless.io/consumer/server-api/operations).

### Client State

Use the `generatingClientState` parameter of `BiomEnrollConfig` or `BiomAuthConfig` to create a client state useful for [account recovery](mobile-sdk-account-recovery.html).

### 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

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

#### iOS 5.2

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

#### Flutter

```dart
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

```javascript
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](mobile-sdk-guide.adoc).
