Bio Login with Backend V2
Overview
The Bio Login module verifies a user by capturing a selfie and uploading the captured biometric data to Amani services.
On iOS, BioLogin is created using BioLoginBuilder. The selected capture type determines how the selfie is captured, while the start() and upload() flow remains the same for all capture types.
BioLogin supports the following capture methods:
.manualSelfie— the user manually captures the selfie..autoSelfie— the selfie is captured automatically when the face is positioned correctly..poseEstimation— the user completes a guided head-pose verification flow before capture.
Each
build()call creates a newBioLogininstance. Configuration is not shared between different BioLogin instances.
Requirements
- AmaniSDK
3.7.4or higher. - Xcode 13+.
- Swift.
- Camera permission configured in the application.
- Microphone permission if required by the selected flow.
- A valid Amani server URL.
- A valid BioLogin token.
Basic Flow
The typical BioLogin integration follows these steps:
-
Create a BioLoginBuilder
- Set the server URL.
- Set the BioLogin token.
- Set the internal BioLogin type using
setType(type:). - Select the desired selfie capture type.
-
Configure the selected capture type
- For
.manualSelfieand.autoSelfie, optionally customize selfie messages and colors. - For
.poseEstimation, optionally customize messages, colors, and guide images.
- For
-
Build the BioLogin instance
- Call
build(). - Keep a strong reference to the returned
BioLogininstance until the flow is completed.
- Call
-
Start BioLogin
- Call
start(). - Add the returned
UIViewto your view hierarchy. - The completion callback returns the captured preview image.
- Call
-
Upload the result
- Call
upload()on the sameBioLogininstance. - Handle the success or failure result.
- Remove the BioLogin view when the flow is complete.
- Call
start()andupload()are common to all BioLogin capture types. Only the Builder configuration changes between Manual Selfie, Auto Selfie, and Pose Estimation.
BioLogin Properties
Keep the BioLogin instance and its view as properties while the flow is active:
private var bioLogin: BioLogin?
private var viewContainer: UIView?
Common Builder Parameters
The following parameters can be used for all BioLogin capture types.
Server URL
Use setUrl(url:) to configure the Amani server URL.
.setUrl(
url: "<YOUR_SERVER_URL>"
)
Token
Use setToken(token:) to configure the BioLogin token.
.setToken(
token: "<YOUR_TOKEN>"
)
Type
Use setType(type:) to configure the internal BioLogin type.
.setType(
type: "XXX_SE_0"
)
Default value:
"XXX_SE_0"
setType(type:) can be configured directly from BioLoginBuilder.
For backwards compatibility, it is also available on the created BioLogin instance:
guard let bioLogin = BioLoginBuilder()
.setUrl(url: "<YOUR_SERVER_URL>")
.setToken(token: "<YOUR_TOKEN>")
.setBioLoginType(type: .autoSelfie)
.build()
else {
return
}
bioLogin.setType(
type: "XXX_SE_0"
)
The recommended usage is to set the type directly on the builder before calling build().
BioLogin Capture Type
Use setBioLoginType(type:) to select the capture mode.
.setBioLoginType(
type: .autoSelfie
)
Available values:
.manualSelfie
.autoSelfie
.poseEstimation
Source
source is optional and defaults to 3.
.setSource(
source: 3
)
Comparison Adapter
comparison_adapter is optional and defaults to 2.
The existing public API name is preserved for backwards compatibility:
.setComparisonAdaptere(
comparison_adapter: 2
)
Manual Selfie Capture
Use .manualSelfie when the user should manually trigger the selfie capture.
Create the BioLogin instance as shown below:
guard let bioLogin = BioLoginBuilder()
.setUrl(
url: "<YOUR_SERVER_URL>"
)
.setToken(
token: "<YOUR_TOKEN>"
)
.setType(
type: "XXX_SE_0"
)
.setBioLoginType(
type: .manualSelfie
)
.build()
else {
print("BioLogin could not be created.")
return
}
self.bioLogin = bioLogin
Manual Selfie uses the same message and color configuration APIs as Auto Selfie.
Manual Selfie Messages
Use setSelfieMessages(key:value:) to override individual selfie messages.
guard let bioLogin = BioLoginBuilder()
.setUrl(
url: "<YOUR_SERVER_URL>"
)
.setToken(
token: "<YOUR_TOKEN>"
)
.setType(
type: "XXX_SE_0"
)
.setBioLoginType(
type: .manualSelfie
)
.setSelfieMessages(
key: .lookStraight,
value: "Look straight at the camera."
)
.setSelfieMessages(
key: .faceTooSmall,
value: "Move closer to the camera."
)
.setSelfieMessages(
key: .faceTooBig,
value: "Move away from the camera."
)
.build()
else {
return
}
Manual Selfie Colors
Use setSelfieColor(key:value:) to override individual colors.
.setSelfieColor(
key: .appBackgroundColor,
value: "000000"
)
.setSelfieColor(
key: .appFontColor,
value: "FFFFFF"
)
.setSelfieColor(
key: .primaryButtonBackgroundColor,
value: "FFFFFF"
)
.setSelfieColor(
key: .ovalBorderColor,
value: "FFFFFF"
)
.setSelfieColor(
key: .ovalBorderSuccessColor,
value: "00FF00"
)
Available selfie message keys:
.faceIsOk
.notInArea
.faceTooSmall
.faceTooBig
.completed
.captureDescription
.lookStraight
.holdPhoneVertically
Available selfie color keys:
.appBackgroundColor
.appFontColor
.primaryButtonBackgroundColor
.ovalBorderSuccessColor
.ovalBorderColor
Auto Selfie Capture
Use .autoSelfie when the selfie should be captured automatically after the face is positioned correctly.
guard let bioLogin = BioLoginBuilder()
.setUrl(
url: "<YOUR_SERVER_URL>"
)
.setToken(
token: "<YOUR_TOKEN>"
)
.setType(
type: "XXX_SE_0"
)
.setBioLoginType(
type: .autoSelfie
)
.build()
else {
print("BioLogin could not be created.")
return
}
self.bioLogin = bioLogin
Auto Selfie Messages
Use setSelfieMessages(key:value:) to customize Auto Selfie messages.
.setSelfieMessages(
key: .faceIsOk,
value: "Please stay still."
)
.setSelfieMessages(
key: .notInArea,
value: "Align your face inside the circle."
)
.setSelfieMessages(
key: .faceTooSmall,
value: "Move closer to the camera."
)
.setSelfieMessages(
key: .faceTooBig,
value: "Move away from the camera."
)
.setSelfieMessages(
key: .lookStraight,
value: "Look straight."
)
.setSelfieMessages(
key: .holdPhoneVertically,
value: "Hold the phone vertically."
)
Auto Selfie Colors
Use setSelfieColor(key:value:) to customize the Auto Selfie UI.
.setSelfieColor(
key: .appBackgroundColor,
value: "000000"
)
.setSelfieColor(
key: .appFontColor,
value: "FFFFFF"
)
.setSelfieColor(
key: .primaryButtonBackgroundColor,
value: "FFFFFF"
)
.setSelfieColor(
key: .ovalBorderColor,
value: "FFFFFF"
)
.setSelfieColor(
key: .ovalBorderSuccessColor,
value: "00FF00"
)
The following APIs are shared by .manualSelfie and .autoSelfie:
setSelfieMessages(key:value:)
setSelfieColor(key:value:)
Colors are provided as hexadecimal strings without the # prefix.
Pose Estimation Capture
Use .poseEstimation when the user should complete a guided head-pose verification flow before capture.
guard let bioLogin = BioLoginBuilder()
.setUrl(
url: "<YOUR_SERVER_URL>"
)
.setToken(
token: "<YOUR_TOKEN>"
)
.setType(
type: "XXX_SE_0"
)
.setBioLoginType(
type: .poseEstimation
)
.build()
else {
print("BioLogin could not be created.")
return
}
self.bioLogin = bioLogin
Pose Estimation supports additional customization for:
- Messages
- Colors and screen configuration
- Main guide images
- Secondary guide images
Pose Estimation Messages
Use setPoseEstimationMessages(infoMessages:) to override one or more Pose Estimation messages.
.setPoseEstimationMessages(
infoMessages: [
.faceIsOk: "Please stay still.",
.notInArea: "Align your face inside the circle.",
.faceTooSmall: "Move closer to the camera.",
.faceTooBig: "Move away from the camera.",
.turnRight: "Turn your head right.",
.turnLeft: "Turn your head left.",
.turnUp: "Look up.",
.turnDown: "Look down.",
.lookStraight: "Look straight.",
.completed: "Verification completed."
]
)
Available Pose Estimation message keys include:
.faceIsOk
.notInArea
.faceTooSmall
.faceTooBig
.completed
.turnRight
.turnLeft
.turnUp
.turnDown
.lookStraight
.errorMessage
.tryAgain
.errorTitle
.confirm
.next
.holdPhoneVertically
.informationScreenDesc1
.informationScreenDesc2
.informationScreenTitle
.wrongPose
.descriptionHeader
.closedEyes
Pose Estimation Colors and Screen Configuration
Use setPoseEstimationColors(screenConfig:) to customize Pose Estimation appearance and screen configuration.
.setPoseEstimationColors(
screenConfig: [
.appBackgroundColor: "000000",
.appFontColor: "FFFFFF",
.primaryButtonBackgroundColor: "004CFF",
.primaryButtonTextColor: "FFFFFF",
.ovalBorderColor: "FFFFFF",
.ovalBorderSuccessColor: "00FF00",
.poseCount: "2",
.secondaryGuideVisibility: "true",
.buttonRadius: "10"
]
)
Available Pose Estimation configuration keys include:
.appBackgroundColor
.appFontColor
.primaryButtonBackgroundColor
.primaryButtonTextColor
.ovalBorderSuccessColor
.ovalBorderColor
.poseCount
.secondaryGuideVisibility
.buttonRadius
Pose Estimation Main Guide Images
Use setPoseEstimationMainGuideImages(guideImages:) to replace the default main direction images.
.setPoseEstimationMainGuideImages(
guideImages: [
.mainGuideUp: UIImage(named: "pose_up")!,
.mainGuideDown: UIImage(named: "pose_down")!,
.mainGuideLeft: UIImage(named: "pose_left")!,
.mainGuideRight: UIImage(named: "pose_right")!,
.mainGuideStraight: UIImage(named: "pose_straight")!
]
)
Available main guide image keys:
.mainGuideUp
.mainGuideDown
.mainGuideLeft
.mainGuideRight
.mainGuideStraight
Pose Estimation Secondary Guide Images
Use setPoseEstimationSecondaryImages(guideImages:) to replace the secondary direction guide images.
.setPoseEstimationSecondaryImages(
guideImages: [
.secondaryGuideUp: UIImage(named: "arrow_up")!,
.secondaryGuideDown: UIImage(named: "arrow_down")!,
.secondaryGuideLeft: UIImage(named: "arrow_left")!,
.secondaryGuideRight: UIImage(named: "arrow_right")!
]
)
Available secondary guide image keys:
.secondaryGuideUp
.secondaryGuideDown
.secondaryGuideLeft
.secondaryGuideRight
Complete Pose Estimation Builder Example
guard let bioLogin = BioLoginBuilder()
.setUrl(
url: "<YOUR_SERVER_URL>"
)
.setToken(
token: "<YOUR_TOKEN>"
)
.setType(
type: "XXX_SE_0"
)
.setBioLoginType(
type: .poseEstimation
)
.setPoseEstimationColors(
screenConfig: [
.appBackgroundColor: "000000",
.appFontColor: "FFFFFF",
.primaryButtonBackgroundColor: "004CFF",
.primaryButtonTextColor: "FFFFFF",
.ovalBorderColor: "FFFFFF",
.ovalBorderSuccessColor: "00FF00",
.poseCount: "2",
.secondaryGuideVisibility: "true",
.buttonRadius: "10"
]
)
.setPoseEstimationMessages(
infoMessages: [
.faceIsOk: "Please stay still.",
.notInArea: "Align your face inside the circle.",
.faceTooSmall: "Move closer to the camera.",
.faceTooBig: "Move away from the camera.",
.turnRight: "Turn your head right.",
.turnLeft: "Turn your head left.",
.turnUp: "Look up.",
.turnDown: "Look down.",
.lookStraight: "Look straight.",
.completed: "Verification completed."
]
)
.build()
else {
print("BioLogin could not be created.")
return
}
self.bioLogin = bioLogin
Start
After creating a BioLogin instance with any of the capture types above, call start().
start() returns a UIView that must be added to your view hierarchy.
do {
guard let bioLogin = bioLogin else {
return
}
guard let bioLoginView = try bioLogin.start(
completion: { [weak self, weak bioLogin] previewImage in
guard
let self = self,
let bioLogin = bioLogin
else {
return
}
print("BioLogin capture completed")
bioLogin.upload(
location: nil
) { [weak self] result in
guard let self = self else {
return
}
DispatchQueue.main.async {
if result == true {
print("BioLogin upload successful")
} else {
print("BioLogin upload failed")
}
self.viewContainer?.removeFromSuperview()
self.viewContainer = nil
self.bioLogin = nil
}
}
}
) else {
print("BioLogin.start returned nil view")
return
}
self.viewContainer = bioLoginView
DispatchQueue.main.async { [weak self] in
guard let self = self else {
return
}
bioLoginView.frame = self.view.bounds
self.view.addSubview(bioLoginView)
self.view.bringSubviewToFront(bioLoginView)
}
} catch {
print("BioLogin start error: \(error)")
self.bioLogin = nil
}
The same start() flow is used for:
.manualSelfie
.autoSelfie
.poseEstimation
Upload
After the selfie capture is completed, call upload() on the same BioLogin instance.
bioLogin.upload(
location: nil
) { result in
if result == true {
print("BioLogin upload successful")
} else {
print("BioLogin upload failed")
}
}
An optional CLLocation can also be provided:
bioLogin.upload(
location: currentLocation
) { result in
if result == true {
print("BioLogin upload successful")
}
}
The same
BioLogininstance that performed the capture must be used forupload().
Complete Pose Estimation Integration Example
final class BioLoginViewController: UIViewController {
private var bioLogin: BioLogin?
private var viewContainer: UIView?
func startBioLogin() {
guard let bioLogin = BioLoginBuilder()
.setUrl(
url: "<YOUR_SERVER_URL>"
)
.setToken(
token: "<YOUR_TOKEN>"
)
.setType(
type: "XXX_SE_0"
)
.setBioLoginType(
type: .poseEstimation
)
.build()
else {
print("BioLogin could not be created.")
return
}
self.bioLogin = bioLogin
do {
guard let bioLoginView = try bioLogin.start(
completion: { [weak self, weak bioLogin] previewImage in
guard
let self = self,
let bioLogin = bioLogin
else {
return
}
print("BioLogin capture completed")
bioLogin.upload(
location: nil
) { [weak self] result in
guard let self = self else {
return
}
DispatchQueue.main.async {
if result == true {
print("BioLogin upload successful")
} else {
print("BioLogin upload failed")
}
self.viewContainer?.removeFromSuperview()
self.viewContainer = nil
self.bioLogin = nil
}
}
}
) else {
print("BioLogin.start returned nil view")
return
}
self.viewContainer = bioLoginView
DispatchQueue.main.async { [weak self] in
guard let self = self else {
return
}
bioLoginView.frame = self.view.bounds
self.view.addSubview(bioLoginView)
self.view.bringSubviewToFront(bioLoginView)
}
} catch {
print("BioLogin start error: \(error)")
self.bioLogin = nil
}
}
}
Builder API Reference
Common Configuration
setUrl(url:)
setToken(token:)
setType(type:)
setBioLoginType(type:)
setSource(source:)
setComparisonAdaptere(comparison_adapter:)
Manual / Auto Selfie Configuration
setSelfieMessages(key:value:)
setSelfieColor(key:value:)
Pose Estimation Configuration
setPoseEstimationMessages(infoMessages:)
setPoseEstimationColors(screenConfig:)
setPoseEstimationMainGuideImages(guideImages:)
setPoseEstimationSecondaryImages(guideImages:)
Build
build()
Returns:
BioLogin?
Notes
- Create BioLogin using
BioLoginBuilder. - Each
build()call creates an independentBioLogininstance. BioLogin.sharedInstanceis not used by the Builder.- Set the server with
setUrl(url:). - Set the token with
setToken(token:). - Set the internal type with
setType(type:). setType(type:)is also available directly onBioLoginfor backwards compatibility.- Select the capture mode with
setBioLoginType(type:). - Keep a strong reference to the created
BioLogininstance until capture and upload are completed. - Use the same
BioLogininstance for bothstart()andupload(). .manualSelfieand.autoSelfieusesetSelfieMessagesandsetSelfieColor..poseEstimationuses the dedicated Pose Estimation configuration APIs.- Builder customization values override BioLogin defaults.
- You do not need to provide every message, color, or guide image.
- Colors are provided as hexadecimal strings without the
#prefix. - Call
build()after Builder configuration is complete. - Call
start()only after a successfulbuild().