Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
A description of, and links to, the Keyless sample apps to support integrators with a working example.
Nothing to remember. Nothing to steal. You are the key.
This set of API calls allows you to fetch and manipulate Keyless enabled devices.
This set of API calls allows you to make operations on various Keyless users.
Keyless.showIntroductionScreen {
// Perform actions after user taps CTA
}Keyless.showIntroductionScreen {
// Perform actions after user taps CTA
}//Keyless adds a td claim to the JWTs containing the data you specify
val jwtSigningInfo = JwtSigningInfo(claimTransactionData = "<your custom data")
// if you want to authenticate with biometric
val biomAuthConfig = BiomAuthConfig(jwtSigningInfo = jwtSigningInfo)
// if you want to authenticate with pin
val pinAuthConfig = PinAuthConfig(pin = "1234", jwtSigningInfo = jwtSigningInfo)
// perform the authentication
Keyless.authenticate(
configuration = biomAuthConfig, // pinAuthConfig if you use pin
onCompletion = { /*TODO: process result*/ }
)//Keyless adds a td claim to the JWTs containing the data you specify
let jwtSigningInfo = JwtSigningInfo(claimTransactionData: "<your custom data>")
// if you want to authenticate with biometric
let biomAuthConfig = BiomAuthConfig(jwtSigningInfo: jwtSigningInfo)
// if you want to authenticate with pin
let pinAuthConfig = PinAuthConfig(pin: "1234", jwtSigningInfo: jwtSigningInfo)
// perform the authentication
Keyless.authenticate(
configuration: biomAuthConfig, // pinAuthConfig if you use pin
onCompletion : { /*TODO: process result*/ }
) // Keyless adds a td claim to the JWTs containing the data you specify
const jwtSigningInfo = new JwtSigningInfo('<your custom data>');
// if you want to authenticate with biometric
const biomAuthConfig = new BiomAuthConfig({
jwtSigningInfo: jwtSigningInfo,
});
// if you want to authenticate with pin
const pinAuthConfig = new PinAuthConfig({
pin: '1234',
jwtSigningInfo: jwtSigningInfo,
});
const result = await Keyless.authenticate(
biomAuthConfig // or pinAuthConfig if you use pin
);
result.fold({
onSuccess(data) {
logConsole('Auth result success ' + JSON.stringify(data, null, 2));
},
onFailure(error) {
logConsole('Auth result failure ' + JSON.stringify(error, null, 2));
},
});import 'package:keyless_flutter_sdk/keyless.dart';
import 'package:keyless_flutter_sdk/models/jwt_signing_info.dart';
import 'package:keyless_flutter_sdk/models/configurations/authentication_configuration.dart';
// Keyless adds a td claim to the JWTs containing the data you specify
final jwtSigningInfo = JwtSigningInfo("<your custom data>");
// if you want to authenticate with biometric
final biomAuthConfig = BiomAuthConfig(
jwtSigningInfo: jwtSigningInfo
);
// if you want to authenticate with pin
final pinAuthConfig = PinAuthConfig(
pin: "1234",
jwtSigningInfo: jwtSigningInfo
);
try {
// perform the authentication with either biometric or pin config
final result = await Keyless.instance.authenticate(
biomAuthConfig // or pinAuthConfig if you use pin
);
print("JWT signed successfully: ${result.signedJwt}");
} catch (error) {
print("Authentication failed: $error");
}This page explains how customers can leverage the option to log additional data from the mobile SDK for the purpose of performance monitoring, issue investigation and analytics
lockoutDuration: Long, //seconds - default 300 seconds
lockoutAttemptsResetAfter: Long, //seconds - default 180 seconds
lockoutAttemptsThreshold: Int //number - default 5 attempts
// clientState retrieved from previous step
val clientState = "<your_client_state>"
val enrollConfig = BiomEnrollConfig(clientState = clientState)
Keyless.enroll(
configuration = enrollConfig,
onCompletion = { result ->
when (result) {
is Keyless.KeylessResult.Success -> {
// account recovered
val userId = result.value.userId
}
is Keyless.KeylessResult.Failure -> Log.d("KeylessSDK ", "error code ${result.error.code}")
}
}
)
// ONLY FOR TEST
// Authentication Configuration
val authConfig = BiomAuthConfig(
livenessConfiguration = LivenessSettings.LivenessConfiguration.DEVELOPMENT,
livenessEnvironmentAware = false
)
// Enrollment Configuration
val enrollConfig = BiomEnrollConfig(
livenessConfiguration = LivenessSettings.LivenessConfiguration.DEVELOPMENT,
livenessEnvironmentAware = false
)
// De-Enrollment Configuration
val deEnrollConfig = BiomDeEnrollConfig(
livenessConfiguration = LivenessSettings.LivenessConfiguration.DEVELOPMENT,
livenessEnvironmentAware = false
)// photoBitmap is the bitmap you created from the document photo.
val configuration = PhotoEnrollConfig(photo = photoBitmap)
Keyless.enroll(
configuration = configuration,
onCompletion = { result ->
when (result) {
is Keyless.KeylessResult.Success -> Log.d("KeylessSDK ", "Enroll success - userId ${result.value.keylessId}")
is Keyless.KeylessResult.Failure -> Log.d("KeylessSDK ", "Enroll failure - error code ${result.error.code}")
}
}
)// photoUIImage is the UIImage you created from the document photo.
let configuration = PhotoEnrollConfig(photo: photoUIImage)
Keyless.enroll(
configuration: configuration,
onCompletion: { result in
switch result {
case .success(let enrollmentSuccess):
print("Enrollment finished successfully. UserID: \(enrollmentSuccess.keylessId)")
case .failure(let error):
print("Enrollment finished with error: \(error.message)
}
})val configuration = BiomDeEnrollConfig()
Keyless.deEnroll(
deEnrollmentConfiguration = configuration,
onCompletion = { result ->
when (result) {
is Keyless.KeylessResult.Success -> Log.d("KeylessSDK ", "De-enroll success")
is Keyless.KeylessResult.Failure -> Log.d("KeylessSDK ", "De-enroll failure - error code ${result.error.code}")
}
}
)let configuration = BiomDeEnrollConfig()
.build()
Keyless.deEnroll(
deEnrollmentConfiguration: configuration,
onCompletion: { error in
if let error = error {
print("De-Enrollment finished with error: \(error.message)")
} else {
print("De-Enrollment finished with success")
}
}
}
// clientState retrieved from previous step
let clientState = "<your_client_state>"
let enrollConfig = BiomEnrollConfig(clientState: clientState)
Keyless.enroll(
configuration: enrollConfig,
onCompletion: { result in
switch result {
case .success(let enrollSuccess):
// account recovered
let userId = enrollSuccess.userId
case .failure(let error):
print("error code: \(error.code)
}
})import 'package:keyless_flutter_sdk/keyless.dart';
import 'package:keyless_flutter_sdk/models/configurations/enrollment_configuration.dart';
// temporaryState retrieved from previous step
final temporaryState = "<your_temporary_state>";
final enrollConfig = BiomEnrollConfig(temporaryState: temporaryState);
try {
final result = await Keyless.instance.enroll(enrollConfig);
// account recovered
print("Account recovered successfully. UserID: ${result.keylessId}");
} catch (error) {
print("Account recovery failed: $error");
}const clientState = '<your client state';
const config = new BiomEnrollConfig({
clientState: clientState,
});
const result = await Keyless.enroll(config);
result.fold({
onSuccess(data) {
logConsole('Enroll result success ' + JSON.stringify(data, null, 2));
},
onFailure(error) {
logConsole('Enroll result failure ' + JSON.stringify(error, null, 2));
},
});// ONLY FOR TEST
// Authentication Configuration
let authConfig = BiomAuthConfig(
livenessConfiguration: Keyless.LivenessConfiguration.DEVELOPMENT
livenessEnvironmentAware: false
)
// Enrollment Configuration
let enrollConfig = BiomEnrollConfig(
livenessConfiguration: Keyless.LivenessConfiguration.DEVELOPMENT
livenessEnvironmentAware: false
)
// De-Enrollment Configuration
let deEnrollConfig = BiomDeEnrollConfig(
livenessConfiguration: Keyless.LivenessConfiguration.DEVELOPMENT
livenessEnvironmentAware: false
)// ONLY FOR TEST
// Authentication Configuration
final authConfig = BiomAuthConfig(
livenessConfiguration: LivenessConfiguration.PASSIVE_STANDALONE_MEDIUM
// livenessEnvironmentAware: false - not available yet
);
// Enrollment Configuration
final enrollConfig = BiomEnrollConfig(
livenessConfiguration: LivenessConfiguration.PASSIVE_STANDALONE_MEDIUM
// livenessEnvironmentAware: false - not available yet
);
// De-Enrollment Configuration
final deEnrollConfig = BiomDeEnrollConfig(
livenessConfiguration: LivenessConfiguration.PASSIVE_STANDALONE_MEDIUM
// livenessEnvironmentAware: false - not available yet
);// ONLY FOR TEST
// Authentication Configuration
const authConfig = new BiomAuthConfig({
livenessConfiguration: LivenessConfiguration.PASSIVE_STANDALONE_MEDIUM,
livenessEnvironmentAware: false,
});
// Enrollment Configuration
const enrollConfig = new BiomEnrollConfig({
livenessConfiguration: LivenessConfiguration.PASSIVE_STANDALONE_MEDIUM,
livenessEnvironmentAware: false,
});
// De-Enrollment Configuration
const deEnrollConfig = new BiomDeEnrollConfig({
livenessConfiguration: LivenessConfiguration.PASSIVE_STANDALONE_MEDIUM,
livenessEnvironmentAware: false,
});
import 'package:keyless_flutter_sdk/keyless.dart';
import 'package:keyless_flutter_sdk/models/configurations/enrollment_configuration.dart';
// documentImage from eDocument.
final configuration = PhotoEnrollConfig(documentImage: documentImage);
try {
final result = await Keyless.instance.enroll(configuration);
print("Enrollment finished successfully. UserID: ${result.keylessId}");
} catch (error) {
print("Enrollment finished with error: $error");
}const config = new PhotoEnrollConfig({
photoBase64: '<photoBase64>',
});
const result = await Keyless.enroll(config);
result.fold({
onSuccess(data) {
logConsole('Enroll result success ' + JSON.stringify(data, null, 2));
},
onFailure(error) {
logConsole('Enroll result failure ' + JSON.stringify(error, null, 2));
},
});public data class PhotoEnrollConfig(
public val photo: Bitmap,
public val temporaryState: String? = null,
public val operationInfo: OperationInfo? = null,
public val jwtSigningInfo: JwtSigningInfo? = null
)public struct PhotoEnrollConfig{
public let photo: CGImage
public let operationInfo: Keyless.OperationInfo?
public let jwtSigningInfo: JwtSigningInfo?
public let temporaryState: String?
}class PhotoEnrollConfig{
final Uint8List? documentImage;
final String? temporaryState;
final OperationInfo? operationInfo;
final JwtSigningInfo? jwtSigningInfo;
}
class PhotoEnrollConfig {
public readonly photoBase64: string;
public readonly operationInfo: OperationInfo | null;
public readonly jwtSigningInfo: JwtSigningInfo | null;
public readonly clientState: string | null;
data class EnrollmentSuccess(
val signedJwt: String? = null,
) : KeylessSdkSuccess()public struct EnrollmentSuccess {
public let signedJwt: String?
}class EnrollmentSuccess {
final String? signedJwt;
} class EnrollmentSuccess {
public readonly keylessId: string;
public readonly customSecret: string;
public readonly enrollmentFrame: string | null;
public readonly signedJwt: string | null;
public readonly clientState: string | null;
}val configuration = DeEnrollmentConfiguration.builder.build()
Keyless.deEnroll(
deEnrollmentConfiguration = configuration,
onCompletion = { result ->
when (result) {
is Keyless.KeylessResult.Success -> Log.d("KeylessSDK ", "De-enroll success")
is Keyless.KeylessResult.Failure -> Log.d("KeylessSDK ", "De-enroll failure - error code ${result.error.code}")
}
}
)let configuration = Keyless.DeEnrollmentConfiguration.builder
.build()
Keyless.deEnroll(
deEnrollmentConfiguration: configuration,
onCompletion: { error in
if let error = error {
print("De-Enrollment finished with error: \(error.message)")
} else {
print("De-Enrollment finished with success")
}
}
}import 'package:keyless_flutter_sdk/keyless.dart';
import 'package:keyless_flutter_sdk/models/configurations/deenrollment_configuration.dart';
// Biometric de-enrollment
final configuration = BiomDeEnrollConfig(
livenessConfiguration: LivenessConfiguration.passiveStandaloneHigh,
livenessTimeout: 60,
cameraDelaySeconds: 0
);
// Or PIN-based de-enrollment
final configuration = PinDeEnrollConfig(
pin: "1234"
);
try {
await Keyless.instance.deEnroll(configuration);
print("De-enrollment successful");
} catch (error) {
print("De-enrollment failed: $error");
}import Keyless, {
BiomDeEnrollConfig,
PinDeEnrollConfig,
LivenessConfiguration
} from '@react-native-keyless/sdk';
// Biometric de-enrollment
const biometricDeEnroll = async () => {
const config = new BiomDeEnrollConfig();
const result = await Keyless.deEnroll(config);
result.fold({
onSuccess: () => {
console.log('De-enrollment successful');
},
onFailure: (error) => {
console.error('De-enrollment failed:', error);
},
});
};
// PIN-based de-enrollment
const pinDeEnroll = async () => {
const config = new PinDeEnrollConfig('1234');
const result = await Keyless.deEnroll(config);
result.fold({
onSuccess: () => {
console.log('De-enrollment successful');
},
onFailure: (error) => {
console.error('De-enrollment failed:', error);
},
});
};DEVELOPMENT
LEVEL_1 //recommended configuration
LEVEL_2val setup = SetupConfig(
apiKey = "...",
let configuration = SetupConfig(
apiKey: "some api key
Keyless.customLogs.collect { logEvent ->
// handle the logEvent
}val setup = SetupConfig(
apiKey = "...",
var myEventCollection = [LogEvent]()
let configuration = Keyless.SetupConfiguration
Get the customer public key in PEM format
The customer service api key
The public key in PEM format
Request is invalid and shouldn't be retried if the request is unchanged
Unauthorized request, the request can't be processed unless you provide a valid authentication method
Not acceptable representation
Get all user authentications in the last 10 minutes using the External User ID (i.e. the unique identifier the user is identified by in your own system). This can be optionally filtered by operation id in order to return a specific transaction/authentication attempt.
val setupConfiguration = SetupConfiguration.builder
.withApiKey("")
.withHosts(listOf("..."))
.withLogging(
keylessLogsConfiguration = LogsConfiguration(enabled = true),
customLogsConfiguration = LogsConfiguration(enabled = true, logLevel = LogLevels.INFO)
)
.build()let configuration = Keyless.SetupConfiguration
.builder
.withApiKey("some api key")
.withHosts(["some.host"])
.withLogging(
keylessLogsConfiguration: KeylessLogsConfiguration(enabled: true, logLevel: .INFO),
customLogsConfiguration: CustomLogsConfiguration(enabled: true, callback: { event in
print(event)
})
)
.build()
Keyless.configure(setupConfiguration: configuration) { error in
// handle error
}final configuration = SetupConfiguration(
apiKey: apiKey,
hosts: [host],
loggingEnabled: true,
loggingLevel: LogLevel.info));
try {
final result = await Keyless.instance.configure(configuration);
print("Configure finished succcessfully.");
} catch (error) {
print("Configure finished with error: $error");
} const config = new SetupConfig({
apiKey: 'apiKey',
hosts: ['HOSTS'],
keylessLogsConfiguration: new LogsConfiguration({
enabled: true,
logLevel: LogLevels.INFO,
}),
customLogsConfiguration: new LogsConfiguration({
enabled: true,
logLevel: LogLevels.TRACE,
}),
});
const result = await Keyless.configure(config);
result.fold({
onSuccess: _data => {
//Handle success
},
onFailure: _error => {
//Handle error
},
//Keyless adds a td claim to the JWTs containing the data you specify
val dynamicLinkingInfo = DynamicLinkingInfo(transactionData = "<your transaction data to display and sign>")
// authenticate with biometric
val biomAuthConfig = BiomAuthConfig(dynamicLinkingInfo = dynamicLinkingInfo)
// perform the authentication
Keyless.authenticate(
configuration = biomAuthConfig,
onCompletion = { /*TODO: process result*/ }
)//Keyless adds a td claim to the JWTs containing the data you specify
let dynamicLinkingInfo = DynamicLinkingInfo(transactionData = "<your transaction data to display and sign>")
// authenticate with biometric
let biomAuthConfig = BiomAuthConfig(dynamicLinkingInfo: dynamicLinkingInfo)
// perform the authentication
Keyless.authenticate(
configuration: biomAuthConfig,
onCompletion: { /*TODO: process result*/ }
)import 'package:keyless_flutter_sdk/keyless.dart';
import 'package:keyless_flutter_sdk/models/configurations/authentication_configuration.dart';
import 'package:keyless_flutter_sdk/models/dynamic_linking_info.dart';
final dynamicLinkingInfo = DynamicLinkingInfo(transactionData: "<your transaction data to display and sign>");
// authenticate with biometric
final biomAuthConfig = BiomAuthConfig(dynamicLinkingInfo: dynamicLinkingInfo);
try {
// perform the authentication
final result = await Keyless.instance.authenticate(biomAuthConfig);
// process the signed JWT from result.signedJwt
print("Authentication successful. Signed JWT: ${result.signedJwt}");
} catch (error) {
print("Authentication failed: $error");
}[
{key1 : value1},
{key2 : value2},
...
{keyN: valueN}
]// JWT header
{
"alg": "ES256",
"typ": "JWT",
"kid": "PIN/FACE"
}
// JWT payload
{
"iat": 1720519812,
"td": "your transaction data to display and sign",
"version": "1.1.0",
"sub": "keyless_id",
"external_user_id": "external user id only if present"
}The customer service api key
The user id
User id set and managed by the client
External user created
Request is invalid and shouldn't be retried if the request is unchanged
Unauthorized request, the request can't be processed unless you provide a valid authentication method
Resource not found
Not acceptable representation
The requested operation conflicts with the current state of the server
Media type not supported, the request can't be processed
An internal error occurred, please try again later or contact the support.
The user id
User id set and managed by the client
External user patched
Request is invalid and shouldn't be retried if the request is unchanged
Unauthorized request, the request can't be processed unless you provide a valid authentication method
Resource not found
Not acceptable representation
Media type not supported, the request can't be processed
An internal error occurred, please try again later or contact the support.
The customer-meaningful user id. Case-sensitive
External user deleted. If the external user does not exist, the response is still positive
Request is invalid and shouldn't be retried if the request is unchanged
Unauthorized request, the request can't be processed unless you provide a valid authentication method
Resource not found
Not acceptable representation
An internal error occurred, please try again later or contact the support.
No content
The customer-meaningful user id. Case-sensitive
All users found bound to external user id. Empty if none is found
Request is invalid and shouldn't be retried if the request is unchanged
Unauthorized request, the request can't be processed unless you provide a valid authentication method
Resource not found
Not acceptable representation
The requested operation conflicts with the current state of the server
An internal error occurred, please try again later or contact the support.
The user id
An user's pending operations
Request is invalid and shouldn't be retried if the request is unchanged
Unauthorized request, the request can't be processed unless you provide a valid authentication method
Resource not found
Not acceptable representation
An internal error occurred, please try again later or contact the support.
Unique operation identifier set and managed by the client
A customer operation
Request is invalid and shouldn't be retried if the request is unchanged
Unauthorized request, the request can't be processed unless you provide a valid authentication method
Resource not found
Not acceptable representation
An internal error occurred, please try again later or contact the support.
The user id
User id set and managed by the client
Unique operation identifier set and managed by the client
Operation payload set and managed by the client
Operation created successfully
Request is invalid and shouldn't be retried if the request is unchanged
Unauthorized request, the request can't be processed unless you provide a valid authentication method
Resource not found
Not acceptable representation
The requested operation conflicts with the current state of the server
Media type not supported, the request can't be processed
An internal error occurred, please try again later or contact the support.
The signed JWT message
The verification completed successfully. Check the result to see if the signature is valid or not
Request is invalid and shouldn't be retried if the request is unchanged
Unauthorized request, the request can't be processed unless you provide a valid authentication method
Not acceptable representation
Media type not supported, the request can't be processed
The user id
User devices
Request is invalid and shouldn't be retried if the request is unchanged
Unauthorized request, the request can't be processed unless you provide a valid authentication method
Resource not found
Not acceptable representation
An internal error occurred, please try again later or contact the support.
The user id
Public signing key
Device successfully deleted
Request is invalid and shouldn't be retried if the request is unchanged
Unauthorized request, the request can't be processed unless you provide a valid authentication method
Resource not found
Not acceptable representation
An internal error occurred, please try again later or contact the support.
The user id
User successfully deleted
Request is invalid and shouldn't be retried if the request is unchanged
Unauthorized request, the request can't be processed unless you provide a valid authentication method
Resource not found
Not acceptable representation
An internal error occurred, please try again later or contact the support.
The user id
Operation id to filter the results
User authentications
Unauthorized request, the request can't be processed unless you provide a valid authentication method
User not found
The customer service api key
The customer-meaningful user id. Case-sensitive
Operation id to filter the results
External user authentications
Unauthorized request, the request can't be processed unless you provide a valid authentication method
External user not found
POST /v2/users/{userId}/external-user HTTP/1.1
X-Api-Key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 25
{
"externalUserId": "text"
}{
"sdkCustomerId": 1,
"userId": "0123456789ABCDEF",
"externalUserId": "text",
"createdAt": "2025-08-06T15:04:05.242194378",
"updatedAt": "2025-08-06T15:04:05.242194378"
}PATCH /v2/users/{userId}/external-user HTTP/1.1
X-Api-Key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 25
{
"externalUserId": "text"
}{
"sdkCustomerId": 1,
"userId": "0123456789ABCDEF",
"externalUserId": "text",
"createdAt": "2025-08-06T15:04:05.242194378",
"updatedAt": "2025-08-06T15:04:05.242194378"
}DELETE /v2/external-users/{externalUserId} HTTP/1.1
X-Api-Key: YOUR_API_KEY
Accept: */*
GET /v2/external-users/{externalUserId}/users HTTP/1.1
X-Api-Key: YOUR_API_KEY
Accept: */*
[
{
"userId": "0123456789ABCDEF",
"biometricPublicSigningKey": "0123456789ABCDEF",
"createdAt": "2025-08-06T15:04:05.242194378",
"updatedAt": "2025-08-06T15:04:05.242194378"
}
]GET /v2/users/{userId}/operations/pending HTTP/1.1
X-Api-Key: YOUR_API_KEY
Accept: */*
[
{
"operationId": "123456abcdef",
"operationPayload": "payload",
"externalUserId": "abcdef123456",
"authType": "biom"
},
{
"operationId": "654321fedcba"
}
]GET /v2/operations/{operationId} HTTP/1.1
X-Api-Key: YOUR_API_KEY
Accept: */*
{
"id": 1,
"timestamp": "2020-01-02T03:04:05.68",
"nodeId": "text",
"userId": "0123456789ABCDEF",
"apiKey": "text",
"externalUserId": "text",
"operationId": "text",
"operationPayload": "text",
"result": true,
"authType": "biom",
"state": "approved"
}POST /v2/users/{userId}/operations HTTP/1.1
X-Api-Key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 72
{
"externalUserId": "text",
"operationId": "text",
"operationPayload": "text"
}{
"success": true
}GET /v2/verify-jwt/public-key HTTP/1.1
X-Api-Key: YOUR_API_KEY
Accept: */*
{
"content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwJ1\n-----END PUBLIC KEY-----"
}POST /v2/verify-jwt HTTP/1.1
X-Api-Key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 18
{
"message": "text"
}{
"result": true
}GET /v2/users/{userId}/devices HTTP/1.1
X-Api-Key: YOUR_API_KEY
Accept: */*
[
{
"userId": "0123456789ABCDEF",
"sdkCustomerId": 1,
"publicSigningKey": "text",
"publicEncryptionKey": "text",
"state": "ACTIVE",
"createdAt": "2020-01-02T03:04:05.242194378",
"osVersion": "text",
"sdkVersion": "text",
"deletedAt": "2020-01-02T03:04:05.242194378"
}
]DELETE /v2/users/{userId}/devices/{publicSigningKey} HTTP/1.1
X-Api-Key: YOUR_API_KEY
Accept: */*
{
"success": true
}DELETE /v2/users/{userId} HTTP/1.1
X-Api-Key: YOUR_API_KEY
Accept: */*
{
"success": true
}GET /v2/users/{userId}/authentications HTTP/1.1
X-Api-Key: YOUR_API_KEY
Accept: */*
{
"page": {
"number": 1,
"totalElements": 1,
"totalPages": 1,
"size": 1
},
"content": [
{
"userId": "0123456789ABCDEF",
"authentications": [
{
"createdAt": "text",
"result": "APPROVED",
"errorCode": 1,
"operationId": "text",
"deviceId": "text",
"authType": "biom"
}
]
}
]
}GET /v2/external-users/{externalUserId}/authentications HTTP/1.1
X-Api-Key: YOUR_API_KEY
Accept: */*
{
"page": {
"number": 1,
"totalElements": 1,
"totalPages": 1,
"size": 1
},
"content": [
{
"externalUserId": "text",
"authentications": [
{
"createdAt": "text",
"result": "APPROVED",
"errorCode": 1,
"operationId": "text",
"deviceId": "text",
"authType": "biom"
}
]
}
]
} const eventSubscription = Keyless.subscribeToCustomLogs(eventLog => {
// Handle log
});
const config = new SetupConfig({
apiKey: 'apiKey',
hosts: ['HOSTS'],
customLogsConfiguration: new LogsConfiguration({
enabled: true,
logLevel: LogLevels.TRACE,
}),
});
const result = await Keyless.configure(config);
result.fold({
onSuccess: _data => {
//Handle success
},
onFailure: _error => {
//Handle error
},
eventSubscription?.unsubscribe();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
}fun getUserId(): KeylessResult<String, KeylessSdkError>func getUserId() -> Result<String, KeylessSDKError>import Keyless from '@react-native-keyless/sdk';
const getUserId = async () => {
const result = await Keyless.getUserId();
result.fold({
onSuccess: (userId) => {
console.log("User ID:", userId);
},
onFailure: (error) => {
console.error("Failed to get user ID:", error);
},
});
};Future<String> getUserId() asyncval enrollConfig = BiomEnrollConfig(generatingClientState = ClientStateType.BACKUP)
Keyless.enroll(
configuration = enrollConfig,
onCompletion = { result ->
when (result) {
is Keyless.KeylessResult.Success -> {
val clientState = result.value.clientState
// store the client state on your backend to recover the account in the future
}
is Keyless.KeylessResult.Failure -> Log.d("KeylessSDK ", "error code ${result.error.code}")
}
}
)
val authConfig = BiomAuthConfig(generatingClientState = ClientStateType.BACKUP)
Keyless.authenticate(
configuration = authConfig,
onCompletion = { result ->
when (result) {
is Keyless.KeylessResult.Success -> {
val clientState = result.value.clientState
// store the client state on your backend to recover the account in the future
}
is Keyless.KeylessResult.Failure -> Log.d("KeylessSDK ", "error code ${result.error.code}")
}
}
)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
}
});
};fun getDevicePublicSigningKey(): KeylessResult<ByteArray, KeylessSdkError>func getDevicePublicSigningKey() -> Result<String, KeylessSDKError>Future<String> getDevicePublicSigningKey() asyncimport 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);
},
});
};fun reset(
onCompletion: (KeylessResult<Unit, KeylessSdkError>) -> Unit
)func reset() -> KeylessSDKError?Future<void> reset() asyncimport Keyless from '@react-native-keyless/sdk';
const resetSdk = async () => {
const result = await Keyless.reset();
result.fold({
onSuccess: () => {
console.log("SDK reset successfully");
},
onFailure: (error) => {
console.error("SDK reset failed:", error);
},
});
};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}")
}
}
}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)")
}
})try {
final rateLimitInfo = await Keyless.instance.getRateLimitInfo();
print("User is rate limited: ${rateLimitInfo.isRateLimited} with remaining seconds: ${rateLimitInfo.remainingSeconds}");
} catch (error) {
print("Error: $error");
}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);
},
});
};"{\"artifact\":{\"family\":\"davideface_lite\",\"version\":\"1.2.0\",\"target\":\"mobile_sdk\",\"liveness\":\"liveness\"},\"core-client-state\":\"BASE_64_STATE\"}"let enrollConfig = BiomEnrollConfig(generatingClientState: .backup)
Keyless.enroll(
configuration: enrollConfig,
onCompletion: { result in
switch result {
case .success(let enrollSuccess):
let clientState = enrollSuccess.clientState
// store the client state on your backend to recover the account in the future
case .failure(let error):
print("error code: \(error.code)
}
})let authConfig = BiomAuthConfig(generatingClientState: .backup)
Keyless.authenticate(
configuration: authConfig,
onCompletion: { result in
switch result {
case .success(let authSuccess):
let clientState = authSuccess.clientState
// store the client state on your backend to recover the account in the future
case .failure(let error):
print("error code: \(error.code)
}
})import 'package:keyless_flutter_sdk/keyless.dart';
import 'package:keyless_flutter_sdk/models/configurations/enrollment_configuration.dart';
final enrollConfig = BiomEnrollConfig(shouldRetrieveTemporaryState: true);
try {
final result = await Keyless.instance.enroll(enrollConfig);
if (result.temporaryState != null) {
// store the temporary state on your backend to recover the account in the future
print("Temporary state retrieved: ${result.temporaryState}");
}
} catch (error) {
print("Enrollment failed: $error");
}import 'package:keyless_flutter_sdk/keyless.dart';
import 'package:keyless_flutter_sdk/models/configurations/authentication_configuration.dart';
final authConfig = BiomAuthConfig(shouldRetrieveTemporaryState: true);
try {
final result = await Keyless.instance.authenticate(authConfig);
if (result.temporaryState != null) {
// store the temporary state on your backend to recover the account in the future
print("Temporary state retrieved: ${result.temporaryState}");
}
} catch (error) {
print("Authentication failed: $error");
}const config = new BiomEnrollConfig({
generatingClientState: ClientStateType.BACKUP,
});
const result = await Keyless.enroll(config);
result.fold({
onSuccess(data) {
logConsole('Enroll result success ' + JSON.stringify(data, null, 2));
const clientState = data.clientState;
// store the client state on your backend to recover the account in the future
logConsole('Client state ' + JSON.stringify(clientState, null, 2));
},
onFailure(error) {
logConsole('Enroll result failure ' + JSON.stringify(error, null, 2));
},
});const config = new BiomAuthConfig({
generatingClientState: ClientStateType.BACKUP,
});
const result = await Keyless.authenticate(config);
result.fold({
onSuccess(data) {
logConsole('Authenticate result success ' + JSON.stringify(data, null, 2));
const clientState = data.clientState;
// store the client state on your backend to recover the account in the future
logConsole('Client state ' + JSON.stringify(clientState, null, 2));
},
onFailure(error) {
logConsole('Authenticate result failure ' + JSON.stringify(error, null, 2));
},
});Common errors, what they mean and recommended next steps.
Use a PIN to perform specific operations when biometric authentication is not necessary
val configuration = PinEnrollConfig(pin = "1234")
let configuration = PinEnrollConfig(pin: "1234")
val configuration = EnrollmentConfiguration.builder
.withPin("1234")
.
let configuration = Keyless.EnrollmentConfiguration.builder
.withPin("1234
val configuration = BiomEnrollConfig()
Keyless.enroll(
let configuration = BiomEnrollConfig()
Keyless.enroll(
val configuration = BiomAuthConfig()
Keyless.authenticate(
let configuration = BiomAuthConfig()
Keyless.authenticate(
val configuration = Keyless.AuthenticationConfiguration()
Keyless.authenticate(
authenticationConfiguration = configuration,
onCompletion = { result ->
when (result) {
is Keyless.KeylessResult.Success -> {
Log.d("IntegratorActivity ", "Authenticate success")
}
is Keyless.KeylessResult.Failure -> {
when (result.error) {
is KeylessUserError.FaceNotMatching -> Log.d("IntegratorActivity ", "Face not matching")
is KeylessUserError.MaskDetected -> Log.d("IntegratorActivity ", "Mask detected")
is KeylessUserError.Spoofing -> Log.d("IntegratorActivity ", "Spoofing detected")
is KeylessUserError.Timeout -> Log.d("IntegratorActivity ", "The operation timed out")
is KeylessUserError.UserCancelled -> Log.d("IntegratorActivity ", "The user cancelled the operation")
is KeylessUserError.NoNetworkConnection -> Log.d("IntegratorActivity ", "No network connection available")
is KeylessUserError.Lockout -> Log.d("IntegratorActivity ", "Your account is temporarily locked")
else -> {
Log.d("IntegratorActivity ", "Authenticate failure")
val errorCode = result.error.code
val errorMessage = result.error.message
val errorCause = result.error.cause?.printStackTrace()
// here you could display a generic error popup with the error code
}
}
}
}
}
)let configuration = Keyless.AuthenticationConfiguration.builder.build()
Keyless.authenticate(authenticationConfiguration: configuration) { result in
switch result {
case .success(let authenticationSuccess):
print("authenticationDidFinish: \(authenticationSuccess.token)")
case .failure(let error):
switch error.kind {
case .userError(let userError):
switch userError {
case .faceNotMatching:
print("Face not matching")
case .maskDetected:
print("Mask detected")
case .spoofing:
print("Spoofing detected")
case .timeout:
print("The operation timed out")
case .userCancelled:
print("The user cancelled the operation")
case .noNetworkConnection:
print("No network connection available")
case .lockout:
print("Your account is temporarily locked")
}
default:
let code = error.code
let message = error.message
// here you could display a generic error popup with the error code
}
}
}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 successful");
} catch (error) {
if (error is KeylessError) {
switch (error.errorType) {
case KeylessErrorType.user:
if (error.code == KeylessErrorCase.faceNotMatching.code) {
print("Face not matching");
} else if (error.code == KeylessErrorCase.maskDetected.code) {
print("Mask detected");
} else if (error.code == KeylessErrorCase.spoofing.code) {
print("Spoofing detected");
} else if (error.code == KeylessErrorCase.timeout.code) {
print("The operation timed out");
} else if (error.code == KeylessErrorCase.userCancelled.code) {
print("The user cancelled the operation");
} else if (error.code == KeylessErrorCase.noNetworkConnection.code) {
print("No network connection available");
} else if (error.code == KeylessErrorCase.deviceTampered.code) {
print("Device security check failed");
} else if (error.code == KeylessErrorCase.lockout.code) {
print("Your account is temporarily locked");
}
break;
default:
// Handle internal or integration errors
print("Authentication failed: ${error.message} (Code: ${error.code})");
// Here you could display a generic error popup with the error code
}
}
}final configuration = PinEnrollConfig(
pin: "myPin"
);
try {
await Keyless.instance.enroll(configuration);
print("Enrollment successful");
} catch (error) {
print("Enrollment failed: $error");
}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));
},
});val configuration = PinAuthConfig(pin = "1234")
Keyless.authenticate(
configuration = configuration,
onCompletion = { /*TODO: process result*/ }
)let configuration = PinAuthConfig(pin: "1234")
Keyless.authenticate(
configuration: configuration,
onCompletion: { /*TODO: process result*/ }
)val configuration = AuthenticationConfiguration.builder
.withPin("1234")
.build()
Keyless.authenticate(
configuration = configuration,
onCompletion = { /*TODO: process result*/ }
)let configuration = Keyless.AuthenticationConfiguration.builder
.withPin("1234")
.build()
Keyless.authenticate(
configuration: configuration,
onCompletion: { /*TODO: process result*/ }
)final configuration = PinAuthConfig(
pin: "1234"
);
try {
final result = await Keyless.instance.authenticate(configuration);
print("Authentication successful");
} catch (error) {
print("Authentication failed: $error");
}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));
},
});val configuration = PinDeEnrollConfig(pin = "1234")
Keyless.deEnroll(
configuration = configuration,
onCompletion = { /*TODO: process result*/ }
)let configuration = PinDeEnrollConfig(pin: "1234")
Keyless.deEnroll(
configuration: configuration,
onCompletion: { /*TODO: process result*/ }
)val configuration =
DeEnrollmentConfiguration.builder
.withPin("myPin")
.build()
Keyless.deEnroll(
configuration = configuration,
onCompletion = { /*TODO: process result*/ }
)let configuration =
Keyless.DeEnrollmentConfiguration.builder
.withPin("myPin")
.build()
Keyless.deEnroll(
configuration: configuration,
onCompletion: { /*TODO: process result*/ }
)final configuration = PinDeEnrollConfig(
pin: "1234"
);
try {
await Keyless.instance.deEnroll(configuration);
print("De-enrollment successful");
} catch (error) {
print("De-enrollment failed: $error");
}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));
},
});val configuration = BiomAuthConfig(shouldRemovePin = true)
Keyless.authenticate(
configuration = configuration,
onCompletion = { /*TODO: process result*/ }
)let configuration = BiomAuthConfig(shouldRemovePin: true)
Keyless.authenticate(
configuration: configuration,
onCompletion: { /*TODO: process result*/ }
)val configuration =
AuthenticationConfiguration.builder
.removingPin()
.build()
Keyless.authenticate(
configuration = configuration,
onCompletion = { /*TODO: process result*/ }
)let configuration =
Keyless.AuthenticationConfiguration.builder
.removingPin()
.build()
Keyless.authenticate(
configuration: configuration,
onCompletion: { /*TODO: process result*/ }
)final configuration = BiomAuthConfig(
shouldRemovePin: true
);
try {
await Keyless.instance.authenticate(configuration);
print("Pin remove successful");
} catch (error) {
print("Pin remove failed: $error");
}
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));
},
});val configuration = PinAuthConfig(pin = "1234", newPin = "5678")
Keyless.authenticate(
configuration = configuration,
onCompletion = { /*TODO: process result*/ }
)let configuration = PinAuthConfig(pin: "1234", newPin: "5678")
Keyless.authenticate(
configuration: configuration,
onCompletion: { /*TODO: process result*/ }
)Future<void> changePin({
required String oldPin,
required String newPin
}) asyncconst 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));
},
});val configuration = PinAuthConfig(pin = "1234", shouldRemovePin = true)
Keyless.authenticate(
configuration = configuration,
onCompletion = { /*TODO: process result*/ }
)let configuration = PinAuthConfig(pin: "1234", shouldRemovePin: true)
Keyless.authenticate(
configuration: configuration,
onCompletion: { /*TODO: process result*/ }
)Future<void> removePin({
required String pin
}) asyncconst 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));
},
});val configuration = EnrollmentConfiguration.builder.build()
Keyless.enroll(
enrollmentConfiguration = configuration,
onCompletion = { result ->
when (result) {
is Keyless.KeylessResult.Success -> Log.d("KeylessSDK ", "Enroll success - userId ${result.value.keylessId}")
is Keyless.KeylessResult.Failure -> Log.d("KeylessSDK ", "Enroll failure - error code ${result.error.code}")
}
}
)let configuration = Keyless.EnrollmentConfiguration.builder.build()
Keyless.enroll(
enrollmentConfiguration: configuration,
onCompletion: { result in
switch result {
case .success(let enrollmentSuccess):
print("Enrollment finished successfully. UserID: \(enrollmentSuccess.keylessId)")
case .failure(let error):
print("Enrollment finished with error: \(error.message)
}
})import 'package:keyless_flutter_sdk/keyless.dart';
import 'package:keyless_flutter_sdk/models/configurations/enrollment_configuration.dart';
final configuration = BiomEnrollConfig();
try {
final result = await Keyless.instance.enroll(configuration);
print("Enrollment finished successfully. UserID: ${result.keylessId}");
} catch (error) {
print("Enrollment finished with error: $error");
}
import Keyless, { BiomEnrollConfig } from '@react-native-keyless/sdk';
const enrollUser = async () => {
const enroll = new BiomEnrollConfig();
const result = await Keyless.enroll(enroll);
result.fold({
onSuccess: (data) => {
console.log(`Enrollment finished successfully. UserID: ${data.keylessId}`);
},
onFailure: (error) => {
console.error('Enrollment finished with error:', error);
},
});
};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}")
}
}
)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
}
})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");
}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);
},
});
};public data class BiomEnrollConfig(
public val cameraDelaySeconds: Int = 2,
public val customSecret: String?,
public val jwtSigningInfo: JwtSigningInfo?,
public val livenessConfiguration: LivenessSettings.LivenessConfiguration = LEVEL_1,
public val livenessEnvironmentAware: Boolean = true,
public val operationInfo: OperationInfo?,
public val shouldRetrieveEnrollmentFrame: Boolean = false,
public val showSuccessFeedback: Boolean = true,
public val showInstructionsScreen: Boolean = true,
public val showFailureFeedback: Boolean = true,
public val generatingClientState: ClientStateType? = null,
public val clientState: String? = null
)public struct BiomEnrollConfig {
public let cameraDelaySeconds: Int
public let customSecret: String?
public let jwtSigningInfo: JwtSigningInfo?
public let livenessConfiguration: Keyless.LivenessConfiguration
public let livenessEnvironmentAware: Bool
public let operationInfo: Keyless.OperationInfo?
public let shouldReturnEnrollmentFrame: Bool
public let showSuccessFeedback: Bool,
public let showInstructionsScreen: Bool,
public let showFailureFeedback: Bool,
public let generatingClientState: ClientStateType?,
public let clientState: String?
}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
)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?
}public interface EnrollmentConfigurationBuilder {
public fun retrievingBackup(): EnrollmentConfigurationBuilder
public fun retrievingTemporaryState(): EnrollmentConfigurationBuilder
public fun savingSecret(customSecret: String): EnrollmentConfigurationBuilder
public fun withBackup(backupKey: ByteArray, backupData: ByteArray): EnrollmentConfigurationBuilder
public fun withDelay(cameraDelaySeconds: Int): EnrollmentConfigurationBuilder
public fun withEnrollmentSelfie(): EnrollmentConfigurationBuilder
public fun withLivenessSettings(
livenessConfiguration: LivenessSettings.LivenessConfiguration,
livenessTimeout: Int
): EnrollmentConfigurationBuilder
public fun withOperationInfo(
operationId: String,
payload: String? = null,
externalUserId: String? = null
): EnrollmentConfigurationBuilder
public fun withPin(pin: String): EnrollmentConfigurationBuilder
public fun withTemporaryState(temporaryState: String): EnrollmentConfigurationBuilder
public fun build(): EnrollmentConfiguration
}public protocol EnrollmentConfigurationBuilder {
public func retrievingBackup() -> EnrollmentConfigurationBuilder
public func retrievingTemporaryState() -> EnrollmentConfigurationBuilder
public func savingSecret(_ customSecret: String) -> EnrollmentConfigurationBuilder
public func withBackup(_ backup: Keyless.Backup) -> EnrollmentConfigurationBuilder
public func withDelay(seconds: Int) -> EnrollmentConfigurationBuilder
public func withEnrollmentSelfie() -> EnrollmentConfigurationBuilder
public func withLivenessSettings(
livenessConfiguration: Keyless.LivenessConfiguration,
livenessTimeout: Int
) -> EnrollmentConfigurationBuilder
public func withOperationInfo(
id: String,
payload: String?,
externalUserId: String?
) -> EnrollmentConfigurationBuilder
public func withPin(_ pin: String) -> EnrollmentConfigurationBuilder
public func withTemporaryState(_ temporaryState: String) -> EnrollmentConfigurationBuilder
public func build() -> Keyless.EnrollmentConfiguration
}class BiomEnrollConfig {
final String? customSecret;
final String? temporaryState;
final OperationInfo? operationInfo;
final LivenessConfiguration? livenessConfiguration;
final int? livenessTimeout;
final bool? shouldRetrieveTemporaryState;
final int? cameraDelaySeconds;
final JwtSigningInfo? jwtSigningInfo;
final DynamicLinkingInfo? dynamicLinkingInfo;
final bool? showScreenInstructions;
final bool? showScreenSuccessFlow;
}
// The BiomEnrollConfig can be instantiated with these optional properties.
// example: new BiomEnrollConfig({ customSecret: 'your-secret', cameraDelaySeconds: 3 });
class BiomEnrollConfig {
public readonly livenessConfiguration: LivenessConfiguration;
public readonly livenessEnvironmentAware: boolean;
public readonly cameraDelaySeconds: number;
public readonly generatingClientState: ClientStateType | null;
public readonly shouldRetrieveEnrollmentFrame: boolean;
public readonly clientState: string | null;
public readonly customSecret: string | null;
public readonly iamToken: string | null;
public readonly operationInfo: OperationInfo | null;
public readonly jwtSigningInfo: JwtSigningInfo | null;
public readonly showSuccessFeedback: boolean;
public readonly showFailureFeedback: boolean;
public readonly showScreenInstructions: boolean;
}
data class EnrollmentSuccess(Delaying the Keyless evaluation/decision
By default, our biometric decision making process initiates immediately on the camera being invoked and the camera preview showing. We believe this offers the maximum level of security in that an attacker is given no additional preparation time in front of the camera view, while at the same time we have looked to optimise the experience for genuine users i.e. delivering both approve and reject decisions in a way that feels natural and understandable to users.
However, we recognise that our customers, and their users, have different contexts and preferences and therefore the cameraDelaySeconds configuration is available to specify the delay (in seconds) between when the camera preview appears, and when the liveness processing starts. In effect, no decision, whether
Please note we advise careful consideration when implementing this feature for two reasons:
i) While this allows users to frame themselves and have longer to understand what is happening, is also time for any attackers to also optimise their framing.
ii) Implementing will ultimately mean that the "happy path" flow for all users is extended. If the delay is set for too long, some customers have noted that there is also the potential for some users to become frustrated and cancel/drop the flow.
We're happy to engage further in what the best trade-offs may be for customers, given our wide-ranging experience of assisting customers in live implementations.
val keylessId: String,
val customSecret: String = "",
val signedJwt: String? = null,
val enrollmentFrame: Bitmap? = null,
val temporaryState: String? = null
) : KeylessSdkSuccess()public struct EnrollmentSuccess {
public let keylessId: String?
public let customSecret: String?
public let enrollmentFrame: CGImage?
public let signedJwt: String?
public let clientState: String?
}class EnrollmentSuccess {
final String keylessId;
final String? customSecret;
final String? signedJwt;
final String? clientState;
}
class EnrollmentSuccess {
public readonly keylessId: string;
public readonly customSecret: string;
public readonly enrollmentFrame: string | null;
public readonly signedJwt: string | null;
public readonly clientState: string | null;
}
DEVELOPMENT
LEVEL_1 //recommended configuration
LEVEL_2interface 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
}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
}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;
}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;
}
data class AuthenticationSuccess(
val customSecret: String? = null,
val signedJwt: String? = null,
val clientState: String? = null
) : KeylessSdkSuccess()public struct AuthenticationSuccess {
public let customSecret: String?
public let signedJwt: String?
public let clientState: String?
}class AuthenticationSuccess {
final String? customSecret;
final String? signedJwt;
final String? temporaryState;
}class AuthenticationSuccess {
customSecret: string | null;
signedJwt: string | null;
clientState: string | null;
}DEVELOPMENT
LEVEL_1 //recommended configuration
LEVEL_2val configuration = BiomAuthConfig(presentationStyle = PresentationStyle.NO_CAMERA_PREVIEW)
Keyless.authenticate(configuration = configuration, onCompletion = { result ->
// Handle result
})let configuration = BiomAuthConfig(presentationStyle: .noCameraPreview)
Keyless.authenticate(configuration: configuration, onCompletion: { result in
// Handle result
})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");
}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);
},
});
};LEVEL_1. For more details refet to Liveness Settings section.showScreenSuccessFlowshowSuccessFeedbackAndroid: from keyless-android-sdk to keyless-mobile-sdk
iOS (SPM): from keyless.KeylessSDK to keyless.mobile-sdk
iOS (CocoaPods): from KeylessSDK to keyless-mobile-sdkThe Keyless SDK can be customised in order to provide a more familiar UX when integrated in any custom app.
/repositories section of the settings.gradle file of your Android application, add the following snippet, replacing YOUR_CLOUDSMITH_TOKEN with the CloudSmith token provided to you by Keyless.namespaceKeyless.UI.Color.primary = 0xFF1833B8
Keyless.UI.Color.onPrimary = 0xFFFED900
Keyless.UI.Color.accent =Keyless.UI.Color.primary = .magenta
Keyless.UI.
const ui = new Keyless.UI();
Keyless.UI.Color.sdkTheme = SdkTheme.SYSTEM
// default theme is SYSTEM
public enum class SdkTheme {
DARK,
LIGHT,
SYSTEM
}Keyless.UI.Color.sdkTheme = .system
// default theme is system
public enum SDKTheme {
case dark
case light
case system
}import Keyless, { SdkTheme } from '@react-native-keyless/sdk';
const ui = new Keyless.UI();
ui.color.sdkTheme = Keyless.SdkTheme.LIGHT;
await Keyless.updateUI(ui);
// default theme is SYSTEM
export enum SdkTheme {
SYSTEM = 'SYSTEM',
LIGHT = 'LIGHT',
DARK = 'DARK',
}dependencies {
// ...
implementation 'io.keyless:keyless-mobile-sdk:+'
}android {
// ...
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
// add the following only if you're using Kotlin
kotlinOptions {
jvmTarget = "1.8"
}
}swift package-registry set --global --scope keyless https://swift.cloudsmith.io/keyless/<repo>/
swift package-registry login https://swift.cloudsmith.io/keyless/<repo>/ --token <your-api-token>$ cd your-project-directory
$ pod initecho '${CLOUDSMITH_TOKEN}' | dart pub token add https://dart.cloudsmith.io/keyless/flutter/dart pub add keyless_flutter_sdk:PACKAGE_VERSION --hosted-url https://dart.cloudsmith.io/keyless/flutter/@react-native-keyless:registry=https://npm.cloudsmith.io/keyless/partners-rc/
//npm.cloudsmith.io/keyless/partners/:_authToken=YOUR_CLOUDSMITH_TOKEN# Using npm
npm install @react-native-keyless/sdk
# Using yarn
yarn add @react-native-keyless/sdk<application
...
android:name=".MainApplication"
...
</application>let setupConfig = SetupConfig(
apiKey: "KEYLESS_API_KEY",
hosts: ["KEYLESS_HOSTS"]
)
if let error = Keyless.configure(configuration: setupConfig) {
print("Keyless.Configure failed with error: \(error)")
}// MainApplication
override fun onCreate() {
super.onCreate()
// Initialize Keyless
Keyless.initialize(this)
}<application
...
android:name=".MainApplication"
...
</application>let setupConfiguration = Keyless.SetupConfiguration.builder
.withApiKey("KEYLESS_API_KEY")
.withHosts(["KEYLESS_HOSTS"])
.build()
if let error = Keyless.configure(configuration: setupConfiguration) {
print("Keyless.Configure failed with error: \(error)")
}import 'package:keyless_flutter_sdk/keyless.dart';
import 'package:keyless_flutter_sdk/models/configurations/setup_configuration.dart';final setupConfiguration = SetupConfiguration(
apiKey: "KEYLESS_API_KEY",
hosts: ["KEYLESS_HOSTS"],
);
try {
await Keyless.instance.configure(setupConfiguration);
print("Keyless SDK configured successfully");
// Keyless is ready, you can now call
// enroll/authenticate/deEnroll ...
} catch (error) {
print("Failed to configure Keyless SDK: $error");
// Handle error
}// In MainApplication.kt
import io.reactnative.keyless.sdk.KeylessSDKModule // <-- Add this import
override fun onCreate() {
super.onCreate()
// Initialize Keyless
KeylessSDKModule.initialize(application = this)
// ... rest of your onCreate method
}# Keyless Proguard
-keep class io.keyless.sdk.** {*;}
-keepclassmembers class io.keyless.sdk.** {*;}// MainApplication
override fun onCreate() {
super.onCreate()
// Initialize Keyless
Keyless.initialize(this)
}public interface KLNetworkingModule {
public fun sendHTTPRequest(
baseUrl: String,
path: String,
method: String,
headers: Map<String, String>,
body: String
): KLHTTPResponse
public data class KLHTTPResponse(
val errorCode: Int,
val httpCode: Int,
val responseBody: String
)
}public protocol KLNetworkingModule {
func sendHTTPRequest (
host: String,
url : String,
method: String,
headers : [String: String],
body : String) -> KLHTTPResponse
}
public struct KLHTTPResponse {
var errorCode: Int
var httpCode: Int
var responseBody : String
public init(errorCode: Int, httpCode: Int, responseBody: String) {
self.errorCode = errorCode
self.httpCode = httpCode
self.responseBody = responseBody
}
}dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven {
url "https://dl.cloudsmith.io/YOUR_CLOUDSMITH_TOKEN/keyless/partners/maven/"
}
}
} // MainApplication
override fun onCreate() {
super.onCreate()
// Initialize Keyless
Keyless.initialize(this, "my.app.test")
}// Custom text for introduction
Keyless.UI.Text.Introduction.title = "(custom) Keyless Secure Authentication"
Keyless.UI.Text.Introduction.description = "(custom) Hereon, you will start face scanning..."
Keyless.UI.Text.Introduction.cta = "(custom) Continue"
// Custom text for enrollment
// prelimiar information for enrollment
Keyless.UI.Text.Enrollment.Instruction.title = "(custom) Enroll your face"
Keyless.UI.Text.Enrollment.Instruction.description = "(custom) On the next screen, we will take a photo of your face to create your account."
Keyless.UI.Text.Enrollment.Instruction.tip1 = "(custom) Center your face in the frame"
Keyless.UI.Text.Enrollment.Instruction.tip2 = "(custom) Look directly at the screen"
Keyless.UI.Text.Enrollment.Instruction.tip3 = "(custom) Ensure you are in a well-lit area"
Keyless.UI.Text.Enrollment.Instruction.continueCta = "(custom) Continue"
// Enrollment loading screen
Keyless.UI.Text.Enrollment.Process.title = "(custom 1) Hold on a few seconds"
Keyless.UI.Text.Enrollment.Process.subtitle = "(custom 2) We're creating your private key"
// Error screen
Keyless.UI.Text.Enrollment.Error.title = "(custom) Something went wrong"
Keyless.UI.Text.Enrollment.Error.subtitle = "(custom) Please try again"
Keyless.UI.Text.Enrollment.Error.cta = "(custom) Continue"
// Success screen
Keyless.UI.Text.Enrollment.Success.title = "(custom) Keyless account created successfully!"
Keyless.UI.Text.Enrollment.Success.subtitle = "(custom) Keyless account created successfully!"
Keyless.UI.Text.Enrollment.Success.cta = "(custom) Keyless account created successfully!"
// Custom text for authentication
Keyless.UI.Text.Authentication.Step1.text1 = "(custom) Please look into the camera"
Keyless.UI.Text.Authentication.Step2.text1 = "(custom) Communicating with the Keyless network"
Keyless.UI.Text.Authentication.Step3.text1 = "(custom) Approved"
// Custom text for authentication without camera preview available from version 5.4.1
Keyless.UI.Text.Authentication.NoCameraPreview.lookHere = "(custom) Please look into the camera"
Keyless.UI.Text.Authentication.NoCameraPreview.authenticate = "(custom) Communicating with the Keyless network"
Keyless.UI.Text.Authentication.NoCameraPreview.success = "(custom) Approved"
// Custom text for dynamic linking
Keyless.UI.Text.Authentication.PayloadConfirmation.title = "(custom) Authentication request"
Keyless.UI.Text.Authentication.PayloadConfirmation.subtitle = "(custom) Please, approve the payment to complete the process"
Keyless.UI.Text.Authentication.PayloadConfirmation.denyCta = "(custom) Deny"
Keyless.UI.Text.Authentication.PayloadConfirmation.approveCta = "(custom) Approve"
// Custom text for introduction
Keyless.UI.Text.Introduction.title = "(custom) Keyless Secure Authentication"
Keyless.UI.Text.Introduction.description = "(custom) Hereon, you will start face scanning..."
Keyless.UI.Text.Introduction.cta = "(custom) Continue"
// Custom text for enrollment
// Prelimiar information for enrollment
Keyless.UI.Text.Enrollment.Instruction.title = "(custom) Enroll your face"
Keyless.UI.Text.Enrollment.Instruction.description = "(custom) On the next screen, we will take a photo of your face to create your account."
Keyless.UI.Text.Enrollment.Instruction.tip1 = "(custom) Center your face in the frame"
Keyless.UI.Text.Enrollment.Instruction.tip2 = "(custom) Look directly at the screen"
Keyless.UI.Text.Enrollment.Instruction.tip3 = "(custom) Ensure you are in a well-lit area"
Keyless.UI.Text.Enrollment.Instruction.continueCta = "(custom) Continue"
// Enrollment loading screen
Keyless.UI.Text.Enrollment.Process.title = "(custom 1) Hold on a few seconds"
Keyless.UI.Text.Enrollment.Process.subtitle = "(custom 2) We're creating your private key"
// Error screen
Keyless.UI.Text.Enrollment.Error.title = "(custom) Something went wrong"
Keyless.UI.Text.Enrollment.Error.subtitle = "(custom) Please try again"
Keyless.UI.Text.Enrollment.Error.cta = "(custom) Continue"
// Success screen
Keyless.UI.Text.Enrollment.Success.title = "(custom) Keyless account created successfully!"
Keyless.UI.Text.Enrollment.Success.subtitle = "(custom) Keyless account created successfully!"
Keyless.UI.Text.Enrollment.Success.cta = "(custom) Keyless account created successfully!"
// Custom text for authentication
Keyless.UI.Text.Authentication.Step1.text1 = "(custom) Please look into the camera"
Keyless.UI.Text.Authentication.Step2.text1 = "(custom) Communicating with the Keyless network"
Keyless.UI.Text.Authentication.Step3.text1 = "(custom) Approved"
// Custom text for authentication without camera preview available from version 5.4.1
Keyless.UI.Text.Authentication.NoCameraPreview.lookHere = "(custom) Please look into the camera"
Keyless.UI.Text.Authentication.NoCameraPreview.authenticate = "(custom) Communicating with the Keyless network"
Keyless.UI.Text.Authentication.NoCameraPreview.success = "(custom) Approved"
// Custom text for dynamic linking
Keyless.UI.Text.Authentication.PayloadConfirmation.title = "(custom) Authentication request"
Keyless.UI.Text.Authentication.PayloadConfirmation.subtitle = "(custom) Please, approve the payment to complete the process"
Keyless.UI.Text.Authentication.PayloadConfirmation.denyCta = "(custom) Deny"
Keyless.UI.Text.Authentication.PayloadConfirmation.approveCta = "(custom) Approve"import Keyless from '@react-native-keyless/sdk';
import Keyless from '@react-native-keyless/sdk';
const ui = new Keyless.UI();
// Custom text for introduction
ui.text.introduction.title = '(custom) Keyless Secure Authentication';
ui.text.introduction.description = '(custom) Hereon, you will start face scanning...';
ui.text.introduction.cta = '(custom) Continue';
// Custom text for enrollment
// Prelimiar information for enrollment
ui.text.enrollment.instruction.title = '(custom) Enroll your face';
ui.text.enrollment.instruction.tip1 = '(custom) Center your face in the frame';
ui.text.enrollment.instruction.tip2 = '(custom) Look directly at the screen';
ui.text.enrollment.instruction.tip3 = '(custom) Ensure you are in a well-lit area';
ui.text.enrollment.instruction.continueCta = '(custom) Continue';
// Enrollment loading screen
ui.text.enrollment.process.title = '(custom) Hold on a few seconds';
ui.text.enrollment.process.subtitle = "(custom) We're creating your private key";
// Error screen
ui.text.enrollment.error.title = '(custom) Something went wrong';
ui.text.enrollment.error.subtitle = '(custom) Please try again';
ui.text.enrollment.error.cta = '(custom) Continue';
// Success screen
ui.text.enrollment.success.title = '(custom) Keyless account created successfully!';
ui.text.enrollment.success.subtitle = '(custom) Keyless account created successfully!';
ui.text.enrollment.success.cta = '(custom) Keyless account created successfully!';
// Custom text for authentication
ui.text.authentication.centerFace = '(custom) Please look into the camera';
ui.text.authentication.scan = '(custom) Communicating with the Keyless network';
ui.text.authentication.authenticate = '(custom) Approved';
ui.text.authentication.success = '(custom) Approved';
ui.text.authentication.loading = '(custom) Loading';
// Custom text for dynamic linking
ui.text.authentication.payloadConfirmation.title = '(custom) Authentication request';
ui.text.authentication.payloadConfirmation.subtitle = '(custom) Please, approve the payment to complete the process';
ui.text.authentication.payloadConfirmation.denyCta = '(custom) Deny';
ui.text.authentication.payloadConfirmation.approveCta = '(custom) Approve';
await Keyless.updateUI(ui);// To hide all optional screens
val biomEnrollConfig = BiomEnrollConfig(
showInstructionsScreen = false,
showSuccessFeedback = false,
showFailureFeedback = false
)
Keyless.enroll(
configuration = biomEnrollConfig,
onCompletion = { /* handle completion */ }
)// To hide all optional screens
let biomEnrollConfig = BiomEnrollConfig(
showInstructionsScreen: false,
showSuccessFeedback: false,
showFailureFeedback: false
)
Keyless.enroll(
configuration: biomEnrollConfig,
onCompletion: { _ in /* handle completion */ }
)import Keyless, { BiomEnrollConfig } from '@react-native-keyless/sdk';
const enrollConfig = new BiomEnrollConfig({
showScreenInstructions: false,
showSuccessFeedback: false,
showFailureFeedback: false
});
const result = await Keyless.enroll(enrollConfig);val biomAuthConfig = BiomAuthConfig(
showSuccessFeedback = false
)
Keyless.authenticate(
configuration = biomAuthConfig,
onCompletion = { /* handle completion */ }
)let biomAuthConfig = BiomAuthConfig(
showSuccessFeedback: false
)
Keyless.authenticate(
configuration: biomAuthConfig,
onCompletion: { _ in /* handle completion */ }
)import Keyless, { BiomAuthConfig } from '@react-native-keyless/sdk';
const config = new BiomAuthConfig({
showSuccessFeedback: false,
});
const result = await Keyless.enroll(config);Keyless.UI.Font.customFont: Typeface = Typeface.SERIFKeyless.UI.Font.customFont: String = "Serif"Keyless.UI.hapticFeedbackEnabled = trueKeyless.UI.hapticFeedbackEnabled = falseKeyless.UI.Color.sdkTheme = SdkTheme.SYSTEM
// default theme is SYSTEM
public enum class SdkTheme {
DARK,
LIGHT,
SYSTEM
}Keyless.UI.Color.sdkTheme = .system
// default theme is system
public enum SDKTheme {
case dark
case light
case system
}














Keyless.UI.Color.primary = 0xFF1833B8
Keyless.UI.Color.onPrimary = 0xFFFED900Keyless.UI.Color.primary = .magenta
Keyless.UI.Color.onPrimary = .cyanfinal uiCustomization = UICustomization(
primaryColor: 0xFF1833B8,
onPrimaryColor: 0xFFFED900,
);
// Pass the UI customization when configuring the SDK
final setupConfiguration = SetupConfiguration(
apiKey: "YOUR_API_KEY",
hosts: ["YOUR_HOSTS"],
uiCustomization: uiCustomization
);// Custom text for enrollment
// prelimiar information for enrollment
Keyless.UI.Text.Enrollment.Step0.title = "(custom) Enroll your face"
Keyless.UI.Text.Enrollment.Step0.description = "(custom) On the next screen, we will take a photo of your face to create your account."
Keyless.UI.Text.Enrollment.Step0.prerequisiteCenterFace = "(custom) Center your face in the frame"
Keyless.UI.Text.Enrollment.Step0.prerequisiteDirectLook = "(custom) Look directly at the screen"
Keyless.UI.Text.Enrollment.Step0.prerequisiteWellLitArea = "(custom) Ensure you are in a well-lit area"
Keyless.UI.Text.Enrollment.Step0.prerequisiteRemoveEyeWear = "(custom) Remove any eyewear or hats"
Keyless.UI.Text.Enrollment.Step0.continueCta = "(custom) Continue"
// remaining steps of the enrollment
Keyless.UI.Text.Enrollment.Step1.text1 = "(custom) Put your face within the frame"
Keyless.UI.Text.Enrollment.Step1Success.message = "(custom) Photo captured successfully"
Keyless.UI.Text.Enrollment.Step2.text1 = "(custom 1) Enrolling, please wait…"
Keyless.UI.Text.Enrollment.Step2.text2 = "(custom 2) Enrolling, please wait…"
Keyless.UI.Text.Enrollment.Step2.text3 = "(custom 3) Enrolling, please wait…"
Keyless.UI.Text.Enrollment.Step3.text1 = "(custom) Keyless account created successfully!"
// Custom text for authentication
Keyless.UI.Text.Authentication.Step1.text1 = "(custom) Please look into the camera"
Keyless.UI.Text.Authentication.Step2.text1 = "(custom) Communicating with the Keyless network"
Keyless.UI.Text.Authentication.Step3.text1 = "(custom) Approved"
// Custom text for dynamic linking
Keyless.UI.Text.Authentication.PayloadConfirmation.title = "(custom) Authentication request"
Keyless.UI.Text.Authentication.PayloadConfirmation.subtitle = "(custom) Please, approve the payment to complete the process"
Keyless.UI.Text.Authentication.PayloadConfirmation.denyCta = "(custom) Deny"
Keyless.UI.Text.Authentication.PayloadConfirmation.approveCta = "(custom) Approve"// Custom text for enrollment
// prelimiar information for enrollment
Keyless.UI.Text.Enrollment.Step0.title = "(custom) Enroll your face"
Keyless.UI.Text.Enrollment.Step0.description = "(custom) On the next screen, we will take a photo of your face to create your account."
Keyless.UI.Text.Enrollment.Step0.prerequisiteCenterFace = "(custom) Center your face in the frame"
Keyless.UI.Text.Enrollment.Step0.prerequisiteDirectLook = "(custom) Look directly at the screen"
Keyless.UI.Text.Enrollment.Step0.prerequisiteWellLitArea = "(custom) Ensure you are in a well-lit area"
Keyless.UI.Text.Enrollment.Step0.prerequisiteRemoveEyeWear = "(custom) Remove any eyewear or hats"
Keyless.UI.Text.Enrollment.Step0.continueCta = "(custom) Continue"
// remaining steps of the enrollment
Keyless.UI.Text.Enrollment.Step1.text1 = "(custom) Put your face within the frame"
Keyless.UI.Text.Enrollment.Step1Success.message = "(custom) Position your face within the frame"
Keyless.UI.Text.Enrollment.Step2.text1 = "(custom 1) Enrolling, please wait…"
Keyless.UI.Text.Enrollment.Step2.text2 = "(custom 2) Enrolling, please wait…"
Keyless.UI.Text.Enrollment.Step2.text3 = "(custom 3) Enrolling, please wait…"
Keyless.UI.Text.Enrollment.Step3.text1 = "(custom) Keyless account created successfully!"
// Custom text for authentication
Keyless.UI.Text.Authentication.Step1.text1 = "(custom) Please look into the camera"
Keyless.UI.Text.Authentication.Step2.text1 = "(custom) Communicating with the Keyless network"
Keyless.UI.Text.Authentication.Step3.text1 = "(custom) Approved"
// Custom text for dynamic linking
Keyless.UI.Text.Authentication.PayloadConfirmation.title = "(custom) Authentication request"
Keyless.UI.Text.Authentication.PayloadConfirmation.subtitle = "(custom) Please, approve the payment to complete the process"
Keyless.UI.Text.Authentication.PayloadConfirmation.denyCta = "(custom) Deny"
Keyless.UI.Text.Authentication.PayloadConfirmation.approveCta = "(custom) Approve"final uiCustomization = UICustomization(
// Enrollment Step 0
enrollmentStep0Title: "(custom) Enroll your face",
enrollmentStep0Description: "(custom) On the next screen, we will take a photo of your face to create your account.",
enrollmentStep0PrerequisiteCenterFace: "(custom) Center your face in the frame",
enrollmentStep0PrerequisiteDirectLook: "(custom) Look directly at the screen",
enrollmentStep0PrerequisiteWellLitArea: "(custom) Ensure you are in a well-lit area",
enrollmentStep0PrerequisiteRemoveEyeWear: "(custom) Remove any eyewear or hats",
enrollmentStep0ContinueCta: "(custom) Continue",
// Enrollment Steps
enrollmentStep1Text: "(custom) Put your face within the frame",
enrollmentStep1SuccessText: "(custom) Photo captured successfully",
enrollmentStep2Text1: "(custom 1) Enrolling, please wait…",
enrollmentStep2Text2: "(custom 2) Enrolling, please wait…",
enrollmentStep2Text3: "(custom 3) Enrolling, please wait…",
enrollmentStep2Subtitle: "(custom) Processing your enrollment",
enrollmentStep3Text: "(custom) Keyless account created successfully!",
enrollmentStep3Subtitle: "(custom) You're all set!",
// Authentication Steps
authenticationStep1: "(custom) Please look into the camera",
authenticationStep2: "(custom) Communicating with the Keyless network",
authenticationStep3: "(custom) Approved",
);
// Pass the UI customization when configuring the SDK
final setupConfiguration = SetupConfiguration(
apiKey: "YOUR_API_KEY",
hosts: ["YOUR_HOSTS"],
uiCustomization: uiCustomization
);val biomEnrollConfig = BiomEnrollConfig(
showScreenInstructions = false,
showScreenSuccessFaceCapture = false,
showScreenSuccessFlow = false
)
Keyless.enroll(
configuration = biomEnrollConfig,
onCompletion = { /* handle completion */ }
)let biomEnrollConfig = BiomEnrollConfig(
showScreenSuccessFlow: false,
showScreenSuccessFaceCapture: false,
showScreenInstructions: false
)
Keyless.enroll(
configuration: biomEnrollConfig,
onCompletion: { _ in /* handle completion */ }
)val biomAuthConfig = BiomAuthConfig(
showScreenSuccessFlow = false
)
Keyless.authenticate(
configuration = biomAuthConfig,
onCompletion = { /* handle completion */ }
)let biomAuthConfig = BiomAuthConfig(
showScreenSuccessFlow: false
)
Keyless.authenticate(
configuration: biomAuthConfig,
onCompletion: { _ in /* handle completion */ }
)Keyless.UI.Font.customFont: Typeface = Typeface.SERIFKeyless.UI.Font.customFont: String = "Serif"final uiCustomization = UICustomization(
customFont: "Serif"
);YOUR_CLOUDSMITH_TOKEN<key>NSCameraUsageDescription</key>
<string>Keyless needs access to your camera to enroll and authenticate you. Keyless cannot be used without your camera. Please allow camera permissions.</string><key>NSCameraUsageDescription</key>
<key>BGTaskSchedulerPermittedIdentifiers
// android/settings.gradle
pluginManagement {
plugins {
// ... other plugins
id "org.jetbrains.kotlin.android" version "2.2.0" apply false // ✅ Must be 2.2.0 or higher
}
}<key>NSCameraUsageDescription</key>
<string>This app uses the camera to scan face.</string>cd ios && pod install {
"authentication" : {
"swift.cloudsmith.io" : {
"loginAPIPath" : "/keyless/<repo>",
"type" : "token"
}
},
"registries" : {
"keyless" : {
"supportsAvailability" : false,
"url" : "https://swift.cloudsmith.io/keyless/<repo>/"
}
"version" : 1
}# This is the Keyless repository for partners
source 'https://dl.cloudsmith.io/YOUR_CLOUDSMITH_TOKEN/keyless/partners/cocoapods/index.git'
target 'MyApp' do
use_frameworks!
# Add the Keyless pod
pod 'keyless-mobile-sdk'
endpost_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['ENABLE_BITCODE'] = 'NO'
end
end
end$ pod install
Analyzing dependencies
Cloning spec repo `cloudsmith-YOUR_CLOUDSMITH_TOKEN-keyless-partners-cocoapods-index` from `https://dl.cloudsmith.io/YOUR_CLOUDSMITH_TOKEN/keyless/partners/cocoapods/index.git`flutter pub getallprojects {
repositories {
google()
mavenCentral()
maven {
setUrl("https://dl.cloudsmith.io/YOUR_CUSTOM_TOKEN/keyless/partners/maven/")
}
}
} allprojects {
repositories {
google()
mavenCentral()
maven {
setUrl("https://dl.cloudsmith.io/$cloudsmithToken/keyless/partners/maven/")
}
}
} <provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<meta-data
android:name="io.keyless.fluttersdk.KeylessInitializer"
android:value="androidx.startup" />
</provider>source 'https://dl.cloudsmith.io/YOUR_CUSTOM_TOKEN/keyless/partners/cocoapods/index.git'source 'https://dl.cloudsmith.io/'+ ENV['cloudsmithToken'] +'/keyless/partners/cocoapods/index.git'<key>NSCameraUsageDescription</key>
<string>Keyless needs access to your camera to enroll and authenticate you. Keyless cannot be used without your camera. Please allow camera permissions.</string>
<key>NSMicrophoneUsageDescription</key>
<string>Keyless needs access to your camera to enroll and authenticate you. Keyless cannot be used without your camera. Please allow camera permissions.</string> allprojects {
repositories {
google()
mavenCentral()
maven {
url "https://dl.cloudsmith.io/YOUR_CLOUDSMITH_TOKEN/keyless/partners/maven/"
}
}
}# Add the Keyless source at the top
source 'https://dl.cloudsmith.io/YOUR_CLOUDSMITH_TOKEN/keyless/partners/cocoapods/index.git'
source 'https://cdn.cocoapods.org/'val setupConfig = SetupConfig(
apiKey = "KEYLESS_API_KEY",
hosts = listOf("KEYLESS_HOSTS")
)
Keyless.configure(setupConfig) { result ->
when (result) {
is Keyless.KeylessResult.Success -> {
Log.d("KeylessSDK", "configure success")
// Keyless is ready, you can now call
// enroll/authenticate/deEnroll ...
}
is Keyless.KeylessResult.Failure ->{
Log.d("KeylessSDK", "configure error")
// Inspect result.error for more info
}
}
}val setupConfiguration = SetupConfiguration.builder
.withApiKey("KEYLESS_API_KEY")
.withHosts(listOf("KEYLESS_HOSTS"))
.build()
Keyless.configure(setupConfiguration) { result ->
when (result) {
is Keyless.KeylessResult.Success -> {
Log.d("KeylessSDK", "configure success")
// Keyless is ready, you can now call
// enroll/authenticate/deEnroll ...
}
is Keyless.KeylessResult.Failure ->{
Log.d("KeylessSDK", "configure error")
// Inspect result.error for more info
}
}
} // In MainApplication.kt
import io.reactnative.keyless.sdk.KeylessSDKModule // <-- Add this import
override fun onCreate() {
super.onCreate()
// Initialize Keyless
KeylessSDKModule.initialize(application = this, namespace = "my.app.test")
// ... rest of your onCreate method
} import Keyless, { SetupConfig } from '@react-native-keyless/sdk';
const config = new SetupConfig({
// Make sure to store your keys securely
apiKey: 'KEYLESS_API_KEY',
hosts: ['KEYLESS_HOSTS'],
});
const result = await Keyless.configure(config);
result.fold({
onSuccess: data => {
console.log('Keyless SDK configured successfully:', data);
// Keyless is ready, you can now call other methods
},
onFailure: error => {
console.error('Failed to configure Keyless SDK:', error);
},
});// android/build.gradle
buildscript {
ext {
// ... other variables
kotlinVersion = "2.2.0" // ✅ 1. Define version here (must be 2.2.0 or higher)
}
repositories {
google()
mavenCentral()
}
dependencies {
// ... other classpaths
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion") // ✅ 2. The variable is used on this line
}
}