Face Login
This guide explains how to use the face login feature in the Welcome SDK.
Prerequisites​
First, the user has to be an approved customer by having completed the onboarding flow. Check the image below for more information:
Initialize Incode Welcome SDK as described here​
1:N Face Login - Identify a user​
1:N Face login is suitable if you would like to identify a user by doing a face scan. This will execute a face match comparison across your entire user database and checks if the face corresponds to any of the approved users.
To execute 1:N Face Login call startFaceLogin
method:​
- Java
- Kotlin
IncodeWelcome.getInstance()
.startFaceLogin(activityContext, new SelfieScan.Builder().build(), new SelfieScanListener() {
@Override
public void onSelfieScanCompleted(SelfieScanResult selfieScanResult) {
if (selfieScanResult.status == SelfieScanResult.STATUS_OK) {
FaceLoginResult faceLoginResult = selfieScanResult.faceLoginResult;
if (faceLoginResult != null && faceLoginResult.success) {
String customerUUID = faceLoginResult.customerUUID;
String token = faceLoginResult.token;
String interviewId = faceLoginResult.interviewId;
// ...
} else {
boolean isSpoofAttempt = selfieScanResult.isSpoofAttempt != null ? selfieScanResult.isSpoofAttempt : false;
if (isSpoofAttempt) {
// Liveness failed
} else {
// User's face not found
}
}
} else {
// Some of the preconditions for checking liveness failed, check selfieScanResult.status for specific info
}
}
@Override
public void onError(Throwable error) {
// Some error occurred
}
@Override
public void onUserCancelled() {
// User canceled login
}
});
IncodeWelcome.getInstance()
.startFaceLogin(activityContext, SelfieScan.Builder().build(), object : SelfieScanListener {
override fun onSelfieScanCompleted(selfieScanResult: SelfieScanResult) {
if (selfieScanResult.status == SelfieScanResult.STATUS_OK) {
val faceLoginResult = selfieScanResult.faceLoginResult
if (faceLoginResult != null && faceLoginResult.success) {
val customerUUID = faceLoginResult.customerUUID
val token = faceLoginResult.token
val interviewId = faceLoginResult.interviewId
// ...
} else {
val isSpoofAttempt = selfieScanResult.isSpoofAttempt ?: false
if (isSpoofAttempt) {
// Liveness failed
} else {
// User's face not found
}
}
} else {
// Some of the preconditions for checking liveness failed, check selfieScanResult.status for specific info
}
}
override fun onError(error: Throwable?) {
// Some error occurred
}
override fun onUserCancelled() {
// User canceled login
}
})
1:1 Face Login - Verify the face of a specific user​
1:1 Face Login is suitable if you want do a face authentication for a specific user that is already pre-authorized, meaning you already have the customer's UUID and only want to know if this exact person is trying to authenticate.
To execute 1:1 Face Login call startFaceLogin
method:​
- Java
- Kotlin
IncodeWelcome.getInstance()
.startFaceLogin(activityContext, new SelfieScan.Builder().setCustomerUUID("YOUR_CUSTOMER_ID").build(), new SelfieScanListener() {
@Override
public void onSelfieScanCompleted(SelfieScanResult selfieScanResult) {
if (selfieScanResult.status == SelfieScanResult.STATUS_OK) {
FaceLoginResult faceLoginResult = selfieScanResult.faceLoginResult;
if (faceLoginResult != null && faceLoginResult.success) {
String customerUUID = faceLoginResult.customerUUID;
String token = faceLoginResult.token;
String interviewId = faceLoginResult.interviewId;
// ...
} else {
boolean isSpoofAttempt = selfieScanResult.isSpoofAttempt != null ? selfieScanResult.isSpoofAttempt : false;
if (isSpoofAttempt) {
// Liveness failed
} else {
// User's face is not similar to previously enrolled face
}
}
} else {
// Some of the preconditions for checking liveness failed, check selfieScanResult.status for specific info
}
}
@Override
public void onError(Throwable error) {
// Some error occurred
}
@Override
public void onUserCancelled() {
// User canceled login
}
});
val selfieScanListener = object : SelfieScanListener {
override fun onSelfieScanCompleted(selfieScanResult: SelfieScanResult) {
when (selfieScanResult.status) {
SelfieScanResult.STATUS_OK -> {
val faceLoginResult = selfieScanResult.faceLoginResult
if (faceLoginResult != null && faceLoginResult.success) {
val customerUUID = faceLoginResult.customerUUID
val token = faceLoginResult.token
val interviewId = faceLoginResult.interviewId
// ...
} else {
val isSpoofAttempt = selfieScanResult.isSpoofAttempt ?: false
if (isSpoofAttempt) {
// Liveness failed
} else {
// User's face is not similar to previously enrolled face
}
}
}
else -> {
// Some of the preconditions for checking liveness failed, check selfieScanResult.status for specific info
}
}
}
override fun onError(error: Throwable?) {
// Some error occurred
}
override fun onUserCancelled() {
// User canceled login
}
}
// ...
IncodeWelcome.getInstance()
.startFaceLogin(
activityContext,
SelfieScan.Builder().setCustomerUUID("YOUR_CUSTOMER_ID").build(),
selfieScanListener
)
Face Login result​
The resulting SelfieScanResult
object will have the following:
faceLoginResult
-FaceLoginResult
object that contains:success
- True if face login was successful, false otherwisecustomerUUID
- Customer UUID of the matched user, nil otherwisetoken
- Customer token of the matched user, nil otherwiseinterviewId
- Session interviewId from which the user got approvedinterviewToken
- Session interviewToken which was used during user approvaltransactionId
- Transaction ID of the face login attempt
isSpoofAttempt
- Specifies if there was a spoof attempt or notcroppedSelfieImgPath
- Cropped selfie image location taken during the selfie scan stepfullFrameSelfieImgPath
- Full frame selfie image location taken during the selfie scan stepselfieEncryptedBase64
- Encrypted Base64-encoded selfie imageselfieBase64
- Base64-encoded selfie imageisFaceMatched
- True if face login was successful, false otherwise. Same information as faceLoginResult.successhasFaceMask
- True if a face mask is detected, false otherwise. Null if a check wasn't performederror
- Throwable that describes the error that happened during the face loginresultCode
- Result code common to all IncodeWelcome results
Login parametrization​
By default, Face Login will complete a liveness check and face match on the server, and we highly suggest switching to on-device liveness check and face match in order to improve the speed of Face Login and reduce network traffic, which is particulary important for devices that can have unstable network connections.
To switch to on-device liveness:​
- In your module-level
app/build.gradle
, add additional Incode dependency:
dependencies {
...
implementation 'com.incode.sdk:model-liveness-detection:2.0.0'
implementation 'com.incode.sdk:model-face-recognition:2.0.0'
}
- Specify FaceAuthMode.HYBRID when creating SelfieScan module:
- Java
- Kotlin
SelfieScan selfieScan = new SelfieScan.Builder()
.setFaceAuthMode(SelfieScan.FaceAuthMode.HYBRID)
.build();
val selfieScan = SelfieScan.Builder()
.setFaceAuthMode(SelfieScan.FaceAuthMode.HYBRID)
.build()
To switch to on-device liveness and on-device face recognition include:​
- In your module-level
app/build.gradle
, add an additional Incode dependencies:
dependencies {
...
implementation 'com.incode.sdk:model-liveness-detection:2.0.0'
implementation 'com.incode.sdk:model-face-recognition:2.0.0'
}
- Specify FaceAuthMode.LOCAL when creating SelfieScan module
- Java
- Kotlin
SelfieScan selfieScan = new SelfieScan.Builder()
.setFaceAuthMode(SelfieScan.FaceAuthMode.LOCAL)
.build();
val selfieScan = SelfieScan.Builder()
.setFaceAuthMode(SelfieScan.FaceAuthMode.LOCAL)
.build()
Note: SelfieScan.FaceAuthMode.LOCAL can work only in 1:1 mode and if the user's face template is already saved locally in the device. Templates get saved during successful onboarding or by using the allowFaceAuthModeFallback
parameter (please check explanation below).
Other parameters to consider:
setCustomerUUID
: ID that uniquely identifies the pre-authorized user who is performing a face login. When set, 1:1 login is performed. When this value is null, 1:N login is performed.setShowTutorials
: Show tutorials how to capture selfie before the actual scan.true
by default.setWaitForTutorials
: Hide the continue button in the tutorial screen while tutorial animation is playing, in order to make sure the user has seen the video before continuing.true
by default.setAllowFaceAuthModeFallback
- Specifytrue
if you would want to do aSelfieScan.FaceAuthMode.SERVER
face login in caseSelfieScan.FaceAuthMode.LOCAL
couldn't be performed due to missing the face template on the device. This is applied only to 1:1 Face login.setLensesCheckEnabled
: Set to false if you would like to disable lenses detection during selfie scan.true
by default.setMaskCheckEnabled
: Specifytrue
to enable face mask check detection during face capture.false
by default. The face mask check is performed on the server, unless a local mask detection dependency is included in the module-levelapp/build.gradle
.setBrightnessThreshold
: Adjust the minimum requirements for a well-lit face during capture. Increasing the value will be more restrictive and require better lighting conditions, decreasing the value will loosen requirements and allow capturing while being in a darker environment. You can set the value to 0 to ignore this setting. The value is set at 50 by default.setCameraFacing
: Sets the direction that the camera faces. It can beCameraFacing.FRONT
orCameraFacing.BACK
.CameraFacing.FRONT
by default.setLogAuthenticationEnabled
: Specifyfalse
if, for example, you want to make sure that no network calls are being performed inSelfieScan.FaceAuthMode.LOCAL
mode. Note that the authentication attempts won't be visible in the dashboard.true
by default.setAssistedOnboardingEnabled
: Enables assisted onboarding (back-camera-only onboarding). This is equivalent tosetCameraFacing(CameraFacing.BACK)
.
Kiosk Login​
Kiosk Login is a special face login mode for shared devices with large screens, e.g. tablets. This mode is optimized for a faster login experience. The main factors which accelerate this are:
- Liveness check is disabled.
- Face recognition is done on the server, but without the need to upload a photo. The face template is generated on the device and sent to the server. The server does the match based on the template. The template is significantly smaller than the photo, speeding up the network communication.
- Kiosk Login has a special UX with a full screen camera and relaxed face position constrains.
In order to use Kiosk Login, specify FaceAuthMode.FR_ONLY
when creating the SelfieScan
module:
- Java
- Kotlin
SelfieScan selfieScan = new SelfieScan.Builder()
.setFaceAuthMode(SelfieScan.FaceAuthMode.FR_ONLY)
.build();
val selfieScan = SelfieScan.Builder()
.setFaceAuthMode(SelfieScan.FaceAuthMode.FR_ONLY)
.build()
QR Face Login​
QR Face Login mode is based on offline authentication. It works by matching the face against the face template contained in the QR code. This mode is optimized for a faster login experience. The main factors which accelerate this are:
- Liveness check is disabled.
- Face recognition is done on the device.
In order to use QR Face Login, specify Mode.QR_FACE_LOGIN
when creating the SelfieScan
module:
- java
- Kotlin
SelfieScan selfieScan = new SelfieScan.Builder()
.setFaceAuthMode(SelfieScan.Mode.QR_FACE_LOGIN)
.build();
val selfieScan = SelfieScan.Builder()
.setFaceAuthMode(SelfieScan.Mode.QR_FACE_LOGIN)
.build()
Execute QR Face Login call startQrFaceLogin
method:​
- Java
- Kotlin
IncodeWelcome.getInstance().startQrFaceLogin(activityContext, selfieScan, new QrFaceLoginListener() {
@Override
public void onQrFaceLoginCompleted(QrFaceLoginResult qrFaceLoginResult) {
if (qrFaceLoginResult.isFaceMatched) {
// QR Face login succeeded
} else {
// QR Face login failed
}
}
@Override
public void onError(Throwable error) {
// Some error occurred
}
@Override
public void onUserCancelled() {
// User canceled qr face login
}
});
IncodeWelcome.getInstance().startQrFaceLogin(activityContext, selfieScan, object : QrFaceLoginListener {
override fun onQrFaceLoginCompleted(qrFaceLoginResult: QrFaceLoginResult) {
if (qrFaceLoginResult.isFaceMatched) {
// QR Face login succeeded
} else {
// QR Face login failed
}
}
override fun onError(error: Throwable?) {
// Some error occurred
}
override fun onUserCancelled() {
// User canceled qr face login
}
})