---
title: PIN Authentication
description: Use a PIN to perform specific operations when biometric authentication is not necessary.
component: recognize
page_id: recognize:mobile-sdk:mobile-sdk-pin-authentication
canonical_url: https://docs.pingidentity.com/recognize/mobile-sdk/mobile-sdk-pin-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:
  enrollment-with-pin: Enrollment with PIN
  android: Android
  ios: iOS
  android-4-6: Android 4.6
  ios-4-6: iOS 4.6
  flutter: Flutter
  react-native: React Native
  authentication-with-pin: Authentication with PIN
  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
  de-enrollment-with-pin: De-enrollment with PIN
  android-3: Android
  ios-3: iOS
  android-4-6-3: Android 4.6
  ios-4-6-3: iOS 4.6
  flutter-3: Flutter
  react-native-3: React Native
  remove-pin-keep-biometric-factor: Remove PIN (Keep Biometric Factor)
  android-4: Android
  ios-4: iOS
  android-4-6-4: Android 4.6
  ios-4-6-4: iOS 4.6
  flutter-4: Flutter
  react-native-4: React Native
  pin-utilities: PIN Utilities
  android-5: Android
  ios-5: iOS
  flutter-5: Flutter
  react-native-5: React Native
  android-6: Android
  ios-6: iOS
  flutter-6: Flutter
  react-native-6: React Native
---

# PIN Authentication

For authentication scenarios that do not require biometric recognition, you can use PIN as an alternative.

|   |                                                                                                                                |
| - | ------------------------------------------------------------------------------------------------------------------------------ |
|   | PIN authentication has limited capabilities compared to biometric authentication. PIN supports operation info and JWT signing. |

PingOne Recognize requires at least one of the following authentication factors to be present for each user:

* biometric factor

* PIN factor

PIN factor can be any valid `String`. Numbers are not enforced but are recommended because numeric PINs are familiar for end users.

## Enrollment with PIN

To enroll using the PIN factor, create one of the following configurations.

### Android

```kotlin
val configuration = PinEnrollConfig(pin = "1234")

Keyless.enroll(
  configuration = configuration,
  onCompletion = { /* TODO: process result */ }
)
```

### iOS

```swift
let configuration = PinEnrollConfig(pin: "1234")

Keyless.enroll(
  configuration: configuration,
  onCompletion = { /* TODO: process result */ }
)
```

### Android 4.6

```kotlin
val configuration = EnrollmentConfiguration.builder
  .withPin("1234")
  .build()

Keyless.enroll(
  configuration = configuration,
  onCompletion = { /* TODO: process result */ }
)
```

### iOS 4.6

```swift
let configuration = Keyless.EnrollmentConfiguration.builder
  .withPin("1234")
  .build()

Keyless.enroll(
  configuration: configuration,
  onCompletion = { /* TODO: process result */ }
)
```

### Flutter

```dart
final configuration = PinEnrollConfig(
  pin: "myPin",
);

try {
  await Keyless.instance.enroll(configuration);
  print("Enrollment successful");
} catch (error) {
  print("Enrollment failed: $error");
}
```

### React Native

```text
const config = new PinEnrollConfig({
  pin: '1234',
});

const result = await Keyless.enroll(config);
result.fold({
  onSuccess(data) {
    logConsole('Auth result success ' + JSON.stringify(data, null, 2));
  },
  onFailure(error) {
    logConsole('Enroll result failure ' + JSON.stringify(error, null, 2));
  },
});
```

To enroll multiple authentication factors, call `PingOne Recognize.enroll` once for each factor.

## Authentication with PIN

To authenticate using the PIN factor, create one of the following configurations.

### Android

```kotlin
val configuration = PinAuthConfig(pin = "1234")

Keyless.authenticate(
  configuration = configuration,
  onCompletion = { /* TODO: process result */ }
)
```

### iOS

```swift
let configuration = PinAuthConfig(pin: "1234")

Keyless.authenticate(
  configuration: configuration,
  onCompletion = { /* TODO: process result */ }
)
```

### Android 4.6

```kotlin
val configuration = AuthenticationConfiguration.builder
  .withPin("1234")
  .build()

Keyless.authenticate(
  configuration = configuration,
  onCompletion = { /* TODO: process result */ }
)
```

### iOS 4.6

```swift
let configuration = Keyless.AuthenticationConfiguration.builder
  .withPin("1234")
  .build()

Keyless.authenticate(
  configuration: configuration,
  onCompletion = { /* TODO: process result */ }
)
```

### Flutter

```dart
final configuration = PinAuthConfig(
  pin: "1234",
);

try {
  final result = await Keyless.instance.authenticate(configuration);
  print("Authentication successful");
} catch (error) {
  print("Authentication failed: $error");
}
```

### React Native

```text
const config = new PinAuthConfig({
  pin: '1234',
});

const result = await Keyless.authenticate(config);
result.fold({
  onSuccess(data) {
    logConsole('Auth result success ' + JSON.stringify(data, null, 2));
  },
  onFailure(error) {
    logConsole('Auth result failure ' + JSON.stringify(error, null, 2));
  },
});
```

## De-enrollment with PIN

|   |                                                                                                                          |
| - | ------------------------------------------------------------------------------------------------------------------------ |
|   | De-enrolling deletes both biometric and PIN factors. To remove only the PIN factor, use [PIN utilities](#pin-utilities). |

To de-enroll using the PIN authentication factor, create one of the following configurations.

### Android

```kotlin
val configuration = PinDeEnrollConfig(pin = "1234")

Keyless.deEnroll(
  configuration = configuration,
  onCompletion = { /* TODO: process result */ }
)
```

### iOS

```swift
let configuration = PinDeEnrollConfig(pin: "1234")

Keyless.deEnroll(
  configuration: configuration,
  onCompletion = { /* TODO: process result */ }
)
```

### Android 4.6

```kotlin
val configuration = DeEnrollmentConfiguration.builder
  .withPin("myPin")
  .build()

Keyless.deEnroll(
  configuration = configuration,
  onCompletion = { /* TODO: process result */ }
)
```

### iOS 4.6

```swift
let configuration = Keyless.DeEnrollmentConfiguration.builder
  .withPin("myPin")
  .build()

Keyless.deEnroll(
  configuration: configuration,
  onCompletion = { /* TODO: process result */ }
)
```

### Flutter

```dart
final configuration = PinDeEnrollConfig(
  pin: "1234",
);

try {
  await Keyless.instance.deEnroll(configuration);
  print("De-enrollment successful");
} catch (error) {
  print("De-enrollment failed: $error");
}
```

### React Native

```text
const config = new PinDeEnrollConfig('1234');

const result = await Keyless.deEnroll(config);
result.fold({
  onSuccess(data) {
    logConsole('DeEnroll result success ' + JSON.stringify(data, null, 2));
  },
  onFailure(error) {
    logConsole('DeEnroll result failure ' + JSON.stringify(error, null, 2));
  },
});
```

## Remove PIN (Keep Biometric Factor)

To remove the PIN factor while keeping biometric authentication, perform biometric authentication with `shouldRemovePin = true`.

### Android

```kotlin
val configuration = BiomAuthConfig(shouldRemovePin = true)

Keyless.authenticate(
  configuration = configuration,
  onCompletion = { /* TODO: process result */ }
)
```

### iOS

```swift
let configuration = BiomAuthConfig(shouldRemovePin: true)

Keyless.authenticate(
  configuration: configuration,
  onCompletion = { /* TODO: process result */ }
)
```

### Android 4.6

```kotlin
val configuration = AuthenticationConfiguration.builder
  .removingPin()
  .build()

Keyless.authenticate(
  configuration = configuration,
  onCompletion = { /* TODO: process result */ }
)
```

### iOS 4.6

```swift
let configuration = Keyless.AuthenticationConfiguration.builder
  .removingPin()
  .build()

Keyless.authenticate(
  configuration: configuration,
  onCompletion = { /* TODO: process result */ }
)
```

### Flutter

```dart
final configuration = BiomAuthConfig(
  shouldRemovePin: true,
);

try {
  await Keyless.instance.authenticate(configuration);
  print("Pin remove successful");
} catch (error) {
  print("Pin remove failed: $error");
}
```

### React Native

```text
const config = new BiomAuthConfig({
  shouldRemovePin: true,
});

const result = await Keyless.deEnroll(config);
result.fold({
  onSuccess(data) {
    logConsole('Auth result success ' + JSON.stringify(data, null, 2));
  },
  onFailure(error) {
    logConsole('Auth result failure ' + JSON.stringify(error, null, 2));
  },
});
```

## PIN Utilities

To change the PIN, use `newPin` in `PinAuthConfig`.

### Android

```kotlin
val configuration = PinAuthConfig(pin = "1234", newPin = "5678")

Keyless.authenticate(
  configuration = configuration,
  onCompletion = { /* TODO: process result */ }
)
```

### iOS

```swift
let configuration = PinAuthConfig(pin: "1234", newPin: "5678")

Keyless.authenticate(
  configuration: configuration,
  onCompletion = { /* TODO: process result */ }
)
```

### Flutter

```dart
Future<void> changePin({
  required String oldPin,
  required String newPin
}) async
```

### React Native

```text
const config = new PinAuthConfig({
  pin: '1234',
  newPin: '5678',
});

const result = await Keyless.authenticate(config);
result.fold({
  onSuccess(data) {
    logConsole('Auth result success ' + JSON.stringify(data, null, 2));
  },
  onFailure(error) {
    logConsole('Auth result failure ' + JSON.stringify(error, null, 2));
  },
});
```

To remove the PIN factor and keep biometric enrollment, use `shouldRemovePin` in `PinAuthConfig`.

### Android

```kotlin
val configuration = PinAuthConfig(pin = "1234", shouldRemovePin = true)

Keyless.authenticate(
  configuration = configuration,
  onCompletion = { /* TODO: process result */ }
)
```

### iOS

```swift
let configuration = PinAuthConfig(pin: "1234", shouldRemovePin: true)

Keyless.authenticate(
  configuration: configuration,
  onCompletion = { /* TODO: process result */ }
)
```

### Flutter

```dart
Future<void> removePin({
  required String pin
}) async
```

### React Native

```text
const config = new PinAuthConfig({
  pin: '1234',
  shouldRemovePin: true,
});

const result = await Keyless.authenticate(config);
result.fold({
  onSuccess(data) {
    logConsole('Auth result success ' + JSON.stringify(data, null, 2));
  },
  onFailure(error) {
    logConsole('Auth result failure ' + JSON.stringify(error, null, 2));
  },
});
```
