vFace iOS Integration
This guide covers the vFace biometric and its use in the iOS Veridium SDK. It demonstrates the necessary steps for enrolling, authenticating, template storage options, and UI customisation.
Device Requirements
iOS 12.0 or later
iPhone with 64-bit processor (iPhone 5S or later)
Frameworks
VeridiumVFaceBiometrics
- Contains the SDK interface implementation to the biometric.veridiumVFaceLib
- Contains the core logic of the biometric and is used internally.VeridiumDefaultVFaceUI
- Portrait mode UI and self capture.
In addition to the VFace modules you must also include the following dependencies from the Veridium SDK:
VeridiumCore
VeridiumAnalytics
VeridiumBiometricsOnly
Permissions
Access to the device's camera will be requested upon first use. The app's Info.plist must contain an NSCameraUsageDescription
key with a string value explaining to the user how the app uses camera data.
Privacy Manifest
Your app must include a Privacy manifest file (PrivacyInfo.xcprivacy
). Using the vFace SDK requires only adding the entry for access to User Defaults under NSPrivacyAccessedAPICategoryUserDefaults
with reason “CA92.1
" (access to read an write information accessible to the app itself), as follows:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPrivacyTracking</key>
<false/>
<key>NSPrivacyTrackingDomains</key>
<array/>
<key>NSPrivacyCollectedDataTypes</key>
<array/>
<key>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>CA92.1</string>
</array>
</dict>
</array>
</dict>
</plist>
Initialization and Online Licensing
The Veridium SDK must be initialized with a licence before use, requiring the device to have an active internet connection.
Import the necessary frameworks:
Objective-C
CODE@import VeridiumCore; @import VeridiumBiometricsOnly; @import VeridiumVFaceBiometrics; @import VeridiumDefaultVFaceUI;
Swift
CODEimport VeridiumCore import VeridiumBiometricsOnly import VeridiumVFaceBiometrics import VeridiumDefaultVFaceUI
Request an SDK licence from Veridium and create a licence string:
Objective-C
CODENSString *my_licence = @"licence_key";
Swift
CODElet my_licence = "licence_key"
Call the Veridium SDK setup method with your licence, SDK completion block, and biometric completion block:
Objective-C
CODE[VeridiumSDK setupWithOnlineLicensing:my_licence onSdkLicenseCompletion:^(VeridiumLicenseStatus * _Nullable sdkStatus, NSError * _Nullable error) { // Check licence status and register UIs } onBiolibsCompletion:^(NSDictionary<NSString *,VeridiumLicenseStatus *> * _Nullable licenseStatusDict, NSError * _Nullable error) { // Check biometric licence status }];
Swift
CODEVeridiumSDK.setup(withOnlineLicensing: my_licence, onSdkLicenseCompletion: { sdkStatus, error in // Check licence status and register UIs }, onBiolibsCompletion: {licenseStatusDict, error in // Check biometric licence status })
The onSDKLicenseCompletion block provides the license status of Veridium SDK. Check
sdkStatus.initSuccess
for success andsdkStatus.isInGracePeriod
to warn the licence is in the grace period. In the same block you may register the biometric UI you wish to use for enrolment and authentication.Objective C
CODEif (![sdkStatus initSuccess]) { // handle init fail } if ([sdkStatus isInGracePeriod]) { // handle licence in grace period } [VeridiumSDK.sharedSDK registerDefaultVFaceEnroller]; [VeridiumSDK.sharedSDK registerDefaultVFaceAuthenticator];
Swift
CODEif(!sdkStatus.initSuccess){ // handle init fail } if(sdkStatus.isInGracePeriod) { // handle licence in grace period } VeridiumSDK.shared.registerDefaultVFaceEnroller() VeridiumSDK.shared.registerDefaultVFaceAuthenticator()
The onBiolibsCompletion block provides the license validation status of biometric libraries you registered at step 4. It provides statuses as a dictionary of (libraryName, VeridiumLicenseStatus) key-value pairs. You can iterate over these key-value pairs and check validation statuses.
Please note that, since the initialization involves communication with the Veridium Licensing Server, it is asynchronous. Therefore, the onSDKLicenseCompletion and the onBiolibsCompletion blocks are executed asynchronously.
Local Enrol and Authentication
Manage the local account for enrol and authentication using the VeridiumBiometricsOnly framework.
Perform enrol and authentication using the supplied VeridiumBiometricsOnly framework (import VeridiumBiometricsOnly), which will manage the local account for multiple biometrics.
Objective-C
VeridiumAccount * account;
account = [[ VeridiumAccount alloc] initWithAccountId:@"my_account_id" andService:self];
account.kcStore[@"accountType"] = @"my_account_name";
Swift
var account: VeridiumAccount?;
// Initilise a Veridium account for storage
func initAccount() {
VeridiumSDK.shared.registerLocalAccountService();
account = VeridiumAccount.init(accountId: "my_account_id", andService:VeridiumSDK.shared.localAccountService!);
account!.kcStore["accountType"] = "my_account_name)";
}
Enrolment
First, clear the Veridium account:
account!.clearAllData();
Fetch the VFace enroler and call the enrol method. Provide blocks to handle the possible outcomes:
Swift
let vface_enroller = VeridiumSDK.shared.enrollerVFace!
vface_enroller.enroll({ (enrollmentVector) in
enrollmentVector.store(into: self.account!.kcStore);
VeridiumUtils.alert("Enrollment Success", title:"Success");
}, onFail: {
VeridiumUtils.alert("Enrollment failed", title:"Failed");
}, onCancel: {
VeridiumUtils.alert("Enrollment failed", title:"Cancelled");
}, onError: {
(error) in
VeridiumUtils.alert(error.localizedDescription, title: "Error");
});
Ensure the returned enrolment vector is stored into a VeridiumAccount, as above.
Authentication
Fetch the VFace authenticator and configure with liveness as required:
Swift
let vface_authenticator = VeridiumSDK.shared.authenticatorVFace!
vface_authenticator.config.useLiveness = true
Call the authenticate method and provide blocks to handle the possible outcomes as follows:
vface_authenticator.authenticate("Auth", withCompletion: { (authStatus, error) in
switch (authStatus) {
case VeridiumAuthResult.AUTHENTICATED:
VeridiumUtils.alert("Auth success", title:"Success");
break;
case VeridiumAuthResult.CANCELED:
VeridiumUtils.alert("Auth cancelled", title:"Cancelled");
break;
case VeridiumAuthResult.FAILED:
VeridiumUtils.alert("Auth failed", title:"Failed");
// Detail is available in error.localizedDescription
break;
case VeridiumAuthResult.TIMEOUT:
VeridiumUtils.alert("Auth timeout", title:"Timeout");
break;
case VeridiumAuthResult.AUTHENTICATED_BY_ADMIN:
VeridiumUtils.alert("Authenticated by admin", title:"Admin");
break;
default:
break;
}
});
Match Customization and Auth Template Access
VFace accommodates full customization of the match process by specifying a custom matching strategy and match()
function. This is called once a template is successfully extracted and provides access the authentication template. It should output the result of a match with optional error (or the boolean result of any processing you wish to perform on the auth template).
Inherit VeridiumBiometricMatchingStrategy
class and implement match()
, for example,
import Foundation
import VeridiumCore
class MyMatchingStrategy: NSObject, VeridiumBiometricMatchingStrategy {
var authTemplate_base64: String?
func match(_ probe: VeridiumBiometricVector, whenDone doneBlock: @escaping (Bool, Error?) -> Void)
{
// Process the auth template
authTemplate_base64 = probe.biometricData.base64EncodedString()
return doneBlock(true, nil)
}
}
Passing true to the doneBlock
will propagate to a success result for the capture, false a failure. If no template could be extracted, for example if the user cancels, the match()
is not called.
Image Import
VFace templates can be generated from an image containing a face, and used as an enrolment for authentication. The image will be assessed for quality as follows:
Frontal facing
Central and fully within the image bounds
Adequate lighting
Eyes horizontal and level
Minimum eye separation of 38 pixels
When importing an image, SDK methods return a VeridiumVFaceTemplateResult
which maps to the following:
Code | Description |
---|---|
SUCCESS | Template creation was successful |
FAILED_CGIMAGE_CONVERSION | No face could be detected in the image |
WRONG_PURPOSE | An unsupported operation was requested |
CANNOT_BE_INTERACTIVE | Configuration incorrectly expected a live video stream |
CANNOT_USE_LIVENESS | Liveness cannot be used for imported images |
NO_FACE_FOUND | No face could be detected in the image |
FAILED_QUALITY | The face does not conform to the required quality metrics |
UNSUPPORTED | No support in your licence or platform |
NOT_INITED | The SDK or VFace library has not been initialised |
EXCEPTION | An exception occurred |
Image to template
To generate a template load the image as a CGImage. Fetch either the VFace enroler or authenticator and call the template
method, for example
let vface_operator = VeridiumSDK.shared.enrollerVFace! // For enrolment templates
// let vface_operator = VeridiumSDK.shared.authenticatorVFace! // For auth templates
vface_operator.template(with: image, withCompletion: {templateResult, templateVector in
if templateVector != nil {
// A template was created. Access templateVector.biometricData, of type Data
VeridiumUtils.alert("Template Success", title:"Success");
}else{
// Failed to create a template, check the value of templateResult
switch templateResult {
case VeridiumVFaceTemplateResult.NO_FACE_FOUND:
VeridiumUtils.alert("Template failed", title:"No Face");
return
case VeridiumVFaceTemplateResult.FAILED_QUALITY:
VeridiumUtils.alert("Template failed", title:"Failed Quality");
return
default:
VeridiumUtils.alert("Template failed", title: "Failed")
return
}
}
})
,where templateResult
is of type VeridiumVFaceTemplateResult
.
Note, one of either the enrol or authentication templates must be from a live capture to perform a match.
Authentication With an Image
An image can be used directly for authentication. Load an image as a CGImage. Fetch the VFace enroler and call the authenticate
method, for example,
let authenticator = VeridiumSDK.shared.authenticatorVFace!
authenticator.authenticate(with: image) { authStatus, templateResult, error in
if templateResult != VeridiumVFaceTemplateResult.SUCCESS {
// Failed to make a template from image. Check templateResult values.
VeridiumUtils.alert("Template gn", title: "Failed")
} else {
// authentication was attempted
switch (authStatus) {
case VeridiumAuthResult.AUTHENTICATED:
VeridiumUtils.alert("Auth success", title:"Success");
break;
case VeridiumAuthResult.CANCELED:
VeridiumUtils.alert("Auth cancelled", title:"Cancelled");
break;
case VeridiumAuthResult.FAILED:
VeridiumUtils.alert("Auth failed", title:"Failed");
break;
case VeridiumAuthResult.TIMEOUT:
VeridiumUtils.alert("Auth timeout", title:"Timeout");
break;
case VeridiumAuthResult.AUTHENTICATED_BY_ADMIN:
VeridiumUtils.alert("Authenticated by admin", title:"Admin");
break;
default:
break;
}
}
}
,where templateResult
is of type VeridiumVFaceTemplateResult
.
Liveness
Directed Liveness
Directed Liveness is an active liveness system which instructs the user, with text instructions and visual prompts, to turn their head in a series of randomly chosen directions until the system is satisfied that it is seeing a live user.
The user has a limited amount of time to complete each motion. Failure to complete in time will result in a liveness failure.
Failure to pass liveness halts the capture process and the SDK returns a VeridiumAuthResult.FAILED
result.
Liveness is compulsory during enrolment. Liveness during authentication is optional. To set liveness on/off configure the VFace authenticator:
Swift
let vface_authenticator = VeridiumSDK.shared.authenticatorVFace!
vface_authenticator.config.useLiveness = true
Liveness Factor
The robustness of VFace to a presentation attack is defined by the liveness factor; defined by an integer value between 0 and 99. Higher values trade easy-of-use for higher security. The default value is 50.
The factor controlls the number of motions the user must perform and how strictly they must be followed, as follows.
Value | Name | Description | Motions Required |
---|---|---|---|
0 | OFF | No liveness is applied | na |
1 - 24 | Low | Lowest friction use | 2 |
25 - 74 | Medium | Prioritises easy-of-use | Between 2 and 3 |
75 - 99 | High | Maximum security | Between 3 and 4 |
To set the liveness factor configure the VFace authenticator:
Swift
let vface_authenticator = VeridiumSDK.shared.authenticatorVFace!
vface_authenticator.config.useLiveness = true
vface_authenticator.config.liveness_factor = 75