User and Device Management
The PingOne Recognize SDK caches the enrolled user locally on the device.
There are use cases where it is possible to delete the user from Server API and delete the device from Server API . The PingOne Recognize SDK is not notified about such deletions. For this reason, if you try to authenticate a user or a device that has been deleted from Server API, you get an error.
Call validateUserAndDeviceActive before authenticating to validate that both the user and the device are still active in the PingOne Recognize backend. This avoids asking the user for biometric data when authentication would fail anyway.
Validate User and Device Active
Android
Keyless.validateUserAndDeviceActive(
onCompletion = { result ->
when (result) {
is Keyless.KeylessResult.Success -> Log.d("KeylessSDK ", "user and device active")
is Keyless.KeylessResult.Failure -> Log.d("KeylessSDK ", "user or device not found - error code ${result.error.code}")
// error code 1131 = user is not enrolled on the device (not even locally, so did not check on backend)
// error code 534 = user not found or deactivated on backend
// error code 535 = device not found or deactivated on backend
}
}
)
iOS
Keyless.validateUserDeviceActive(
completionHandler: { error in
if let error = error {
print("user or device deactivated")
// error code 1131 = user is not enrolled on the device (not even locally, so did not check on backend)
// error code 534 = user not found or deactivated on backend
// error code 535 = device not found or deactivated on backend
} else {
print("user and device active")
}
}
)
Flutter
try {
await Keyless.validateUserAndDeviceActive();
print("user and device active");
} catch (error) {
print("user or device deactivated - error code: ${error.code}");
// error code 1131 = user is not enrolled on the device (not even locally, so did not check on backend)
// error code 534 = user not found or deactivated on backend
// error code 535 = device not found or deactivated on backend
}
React Native
import Keyless from '@react-native-keyless/sdk';
const validateUserAndDevice = async () => {
const result = await Keyless.validateUserAndDeviceActive();
result.fold({
onSuccess: () => {
console.log("user and device active");
},
onFailure: (error) => {
console.error(`user or device deactivated - error code: ${error.code}`);
// error code 1131 = user is not enrolled on the device (not even locally)
// error code 534 = user not found or deactivated on backend
// error code 535 = device not found or deactivated on backend
}
});
};
Device Identifier
The device is identified by its public signing key. To retrieve it, use Keyless.getDevicePublicSigningKey().
React Native
import Keyless from '@react-native-keyless/sdk';
const getDevicePublicSigningKey = async () => {
const result = await Keyless.getDevicePublicSigningKey();
result.fold({
onSuccess: (key) => {
console.log("Device public key:", key);
},
onFailure: (error) => {
console.error("Failed to get device public key:", error);
},
});
};
PingOne Recognize SDK Reset
Resetting the PingOne Recognize SDK to a clean state deletes local data from the device, but does not de-enroll the user from the PingOne Recognize backend or deactivate the device from the PingOne Recognize backend.
Lockout Management
The getRateLimitInfo API checks whether the user is currently rate-limited and, if so, for how many seconds. This API is typically used to provide feedback to users after multiple failed authentication attempts.
Android
Keyless.getRateLimitInfo { result ->
when (result) {
is Keyless.KeylessResult.Success -> {
val rateLimitInfo = result.value
println("User is rate limited: ${rateLimitInfo.isRateLimited} with remaining seconds: ${rateLimitInfo.remainingSeconds}")
}
is Keyless.KeylessResult.Failure -> {
println("Error: ${result.error.message}")
}
}
}
iOS
Keyless.getRateLimitInfo(completion: { result in
switch result {
case .success(let success):
print("User is rate limited: \(success.isRateLimited) with remaining seconds: \(success.remainingSeconds)")
case .failure(let error):
print("Error: \(error.message)")
}
})
Flutter
try {
final rateLimitInfo = await Keyless.instance.getRateLimitInfo();
print("User is rate limited: ${rateLimitInfo.isRateLimited} with remaining seconds: ${rateLimitInfo.remainingSeconds}");
} catch (error) {
print("Error: $error");
}
React Native
import Keyless from '@react-native-keyless/sdk';
const getRateLimitInfo = async () => {
const result = await Keyless.getRateLimitInfo();
result.fold({
onSuccess: (info) => {
console.log(`User is rate limited: ${info.isRateLimited}, remaining seconds: ${info.remainingSeconds}`);
},
onFailure: (error) => {
console.error("Error fetching rate limit info:", error);
},
});
};