In this short guide, you will learn how to integrate the Keyless SDK in your Android or iOS mobile application, and enroll and authenticate users through the Keyless platform.
Before jumping into your code editor, make sure that you're familiar with the various components of the authentication system, and common biometic authentication flows.
Prerequisites
Make sure you have both required API keys, and the list of productions hosts from your Keyless contact:
YOUR_CLOUDSMITH_TOKEN to download the SDK from cloudsmith repository
Make sure that your project meets the following requirements:
Your project must target iOS 13 or later.
Swift projects must use Swift 4.0 or later.
Set up a physical iOS device for running your app.
Enable Camera permissions: add the Privacy - Camera Usage Description key in your project’s Info.plist by adding the following (in XCode under Project > Info):
<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>
Background processing. Enable the Background processing mode under Signing & Capabilities/Background Modes. Then, add the following in your project’s Info.plit (in XCode, under the key Permitted background task scheduler identifiers):
Extend any androidX activity that implements the interface for you, for example let your Activity extend the generic ComponentActivity or the more widespread AppCompatActivity.
If you use Proguard, add the following rules to your Proguard configuration file:
# Keyless Proguard
-keep class io.keyless.sdk.** {*;}
-keepclassmembers class io.keyless.sdk.** {*;}
In the the 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.
In the android block of your project build.gradle file, typically app/build.gradle, make sure you have the following options:
android {// ...compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 }// add the following only if you're using KotlinkotlinOptions { jvmTarget ="1.8" }}
Create a Podfile if you don’t already have one
$cdyour-project-directory$podinit
Set up Cocoapods to use your Cloudsmith credentials, by running the following commands, replacing YOUR_CLOUDSMITH_TOKEN with the Cloudsmith token provided you by Keyless.
# This is the Keyless repository for partnerssource 'https://dl.cloudsmith.io/basic/keyless/partners/cocoapods/index.git'target 'MyApp'do use_frameworks!# Add the Keyless pod pod 'KeylessSDK'end
Install the pods. If pod prompts you for authentication insert the string token as your username and then fill in YOUR_CLOUDSMITH_TOKEN as the password.
$podinstallAnalyzingdependenciesCloning spec repo `cloudsmith-basic-keyless-partners-cocoapods-index` from `https://dl.cloudsmith.io/basic/keyless/partners/cocoapods/index.git`
Usernamefor'https://dl.cloudsmith.io':tokenPasswordfor'https://dl.cloudsmith.io':YOUR_CLOUDSMITH_TOKEN
Essential configuration
There is some essential configuration to do before you can use the Keyless SDK.
Initialize the Keyless SDK in your Application class:
Configure the Keyless SDK from your MainActivity, ViewModel or any class you use to communicate with Keyless. Note that configure is asynchronous so wait for the completion callback before calling the next Keyless APIs
The configure method requires a SetupConfiguration as parameter, as well as the KEYLESS_API_KEY and KEYLESS_HOSTS you received from Keyless. You should listen to the result as follows:
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 } } }
Create an instance object of Keyless.SetupConfiguration and pass it to the Keyless.configure method, typically this is done in your app’s application(:didFinishLaunchingWithOptions: method:).
let setupConfiguration = Keyless.SetupConfiguration.builder.withApiKey("KEYLESS_API_KEY").withHosts(["KEYLESS_HOSTS"]).build()iflet error = Keyless.configure(configuration: setupConfiguration) {print("Keyless.Configure failed with error: \(error)")}
Additional configuration
As well as the essential configuration parameters, you can also specify the optional configuration parameters detailed in the following sections.
Logging enabled
Activate logging to the Keyless Management portal with the withLoggingEnabled() method. Logs do not include sensitive user data. Logging is disabled by default.
Lockout policy
Keyless has both client side (applicable to a specific device) and server side (applicable to all users and devices) lockout policies to help prevent brute force attacks.
Client side lockout is configurable in the SDK, and determines how many failed login attempts (lockoutAttemptsThreshold) are allowed over a set time period (lockoutAttemptsResetAfter) before the user is locked out for the set duration (lockoutDuration) on that device.
Account lockoutDuration must be greater than or equal to the lockoutAttemptsResetAfter so that it is not reset by lockoutAttemptsResetAfter.
Server side lockout works similarly, except applies to all authentication devices for a specific user, and is configured to lock a user out for 10 minutes after 5 failed attempts. A successful login resets the count of failed authentication attempts to zero.
Tampered device check
Checking for rooted/jailbroken phones is an unreliable process but you can enable the check with withTamperedDeviceCheck(). If you enable this check, and the SDK detects that phone was tampered with, the Keyless SDK will return an error and prevent the user from authenticating.
Enrollment circuits
To speed up enrollment you can use withNumberOfEnrollmentCircuits(numberOfEnrollmentCircuits: Int) to upload less than the default of five circuits upon enrollment. The remainder (50 - numberOfEnrollmentCircuits) are uploaded asynchronously.
Shared circuits
This is the target desired number of circuits shared between client and server. To set this number call the fun withNumberOfSharedCircuits(numberOfCircuits: Int) function on the SetupConfiguration.builder
val setupConfiguration = SetupConfiguration.builder .withApiKey("KEYLESS_API_KEY") .withHosts(listOf("KEYLESS_HOSTS")) .withNumberOfSharedCircuits(15) .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 } }}
let setupConfiguration = Keyless.SetupConfiguration.builder .withApiKey("KEYLESS_API_KEY") .withHosts(["KEYLESS_HOSTS"]) .withNumberOfSharedCircuits(15) .build()iflet error = Keyless.configure(configuration: setupConfiguration) {print("Keyless.Configure failed with error: \(error)")}
Networking module
If you need to specify a custom module to perform network requests, add withNetworkingModule from the SetupConfigurationBuilder, which must conform to the interface below.