Face Authentication

I. Face Registration

I.1 Face registration from eKYC onboarding user

Use the face from eKYC onboarding to register for face authentication.

Required parameters:

keytyperequireddescriptionmax length
cus_user_idstringyesuser id of customer256
faces[]imagenoselfie image from eKYC onboarding50
face_in_id_cardimagenoimage of the face in id_card
face_typestringnotype of face input (selfie, id_card)
selfie_typestringnoflash_16: Android use SDK TS, flash_8: iOS use SDK TS, vendor_a: use SDK other vendor64

Parameter Selfie Type:

paramAndroidiOSother_vendor
selfie_typeflash_16flash_8vendor_a

Use API directly: Face registration
Use Java SDK: Java API library

Sample code

// Face Auth Registration
String transactionID = "";
Map<String, String> headers = new HashMap<String, String>();
headers.put("X-Request-Id", "use as currently value limit 64 chars");
String cusUserID = "c1b3b3b3-1b3b-4b3b-8b3b-3b3b3b3b3b3b"; // Required

List<TVSyncImage> imagesFaceAuth = Arrays.asList(
        TVSyncImage.createById("3e2693e7-1e8f-40f0-be68-2cf73b09c61b"));
String deviceId = "";
String appId = "";
Double lat = Double.valueOf(0d);
Double lng = Double.valueOf(0d);
String faceType = "selfie";
String selfieType = "flash_16";
TVSyncImage faceInIdCard = TVSyncImage.createById("e975bc8c-9d6e-4118-b905-da8c121636c9");
TVFaceAuthenRegistrationRequest faceAuthRegistrationRequest = TVFaceAuthenRegistrationRequest.builder(cusUserID)
        .cusUserId(cusUserID).faces(imagesFaceAuth).selfieType(selfieType)
        .deviceId(deviceId).appId(appId).lat(lat).lng(lng)
        .faceType(faceType).faceInIdCard(faceInIdCard)
        .build();
TVResponseData<TVFaceAuthenResponse> faceAuthRegistrationResponse = TVApi.getInstance().faceAuthenRegister(faceAuthRegistrationRequest, transactionID, headers);
if (faceAuthRegistrationResponse.hasErrors()) {
    List<TVApiError> errors = faceAuthRegistrationResponse.getErrors();
    System.out.println("Face Auth Registration error:" + errors.get(0).getMessage());
} else {
    System.out.println("Face Auth Registration successful");
}

II. Face Authen

All APIs were called from the Bank's backend. No API calls at SDK. Reference Scenario Scenario 1

Step 1: Get settings from Backend

  • Define flow_id to use for your business: eg. face_auth or reset_password

Use API directly: Get client settings
Use Java SDK: Java API library

Sample code

Java
// Get client settings
String flowID = "face_auth"
TVResponseData<TVClientSettings> response = TVApi.getInstance().getClientSettings(flowID);
if (response.hasErrors()) {
    List<TVApiError> errors = response.getErrors();
    System.out.println("Get client settings error:" + errors.get(0).getMessage());
} else {
    System.out.println("Get client settings successful");
}
System.out.println(response.getRawJSON());

Step 2: Init SDK with settings from Step 1

Pass settings string from step 1 to parameter jsonConfigurationByServer Android: Init SDK
iOS: Init SDK

Sample code

TVInitializeConfiguration config = new TVInitializeConfiguration.Build()
    .setJsonConfigurationByServer(jsonConfigurationByServer)
    .setLanguageCode(languageCode)
    .setTheme(theme)
    .build();

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    TrustVisionSDK.INSTANCE.init(context, config, new BaseTrustVisionSDK.TVInitializeListener() {
        @Override
        public void onInitSuccess() {
            // Start Face Authen
            // eg. startFaceAuthentication(....)
        }

        @Override
        public void onInitError(@NonNull TVDetectionError error) {
            // Handle errors
        }
    });
}

Step 3: Start face authentication after init SDK successfully.

Android: Start Face Authentication
iOS: Start Face Authentication

Parameters:

paramAndroidiOS
authModeauthMode = TVAuthMode.flash16(selfieConfiguration)method: TVFaceAuthenMethod.flash8

Sample code

TVSelfieConfiguration selfieConfiguration = new TVSelfieConfiguration.Builder()
    .setCameraOption(TVSDKConfiguration.TVCameraOption.FRONT)
    .setEnableSound(false)
    .setLivenessMode(TVLivenessMode.PASSIVE)
    .setEnableVerticalChecking(false)
    .setSkipConfirmScreen(false)
    .setEnableUploadFrames(false)
    .setEnableUploadImages(false)
    .setEnableSanityCheck(false)
    .setEnableVerifyLiveness(false)
    .build();
TVFaceAuthenticationConfiguration configuration = TVFaceAuthenticationConfiguration.builder()
        .setCusUserId("")
        .setAuthType(AuthType.AUTH)
        .setAuthMode(TVAuthMode.flash16(selfieConfiguration))
        .setEnableFaceAuthentication(false)
        .setEnableFaceRegistration(false)
        .build();

TrustVisionSDK.INSTANCE.startFaceAuthentication(activity, configuration, new TVCapturingCallBack() {
    @Override
    public void onNewFrameBatch(FrameBatch frameBatch) {
    }

    @Override
    public void onError(TVDetectionError error) {
    }

    @Override
    public void onSuccess(TVDetectionResult result) {
    }

    @Override
    public void onCanceled(){
    }
});

Step 4: Mobile App receives result images, frames videos from SDK

Android: Handle results from SDK
iOS: Handle results from SDK

  1. SDK output result images, and frames videos.
  2. Mobile App upload images and frames videos to server.
  1. After upload all images, frames videos finish go to step 5.

Note: frames video were batched and sent to host app via method onNewFrameBatch to upload async.

Sample code

Map<String, String> selfieFrameBatchIdsDictionary = new HashMap<String, String>();
TrustVisionSDK.INSTANCE.startFaceAuthentication(activity, configuration, new TVCapturingCallBack() {

    // If frameBatch is uploaded to server by the SDK, the host app does not need to override this method
    @Override
    public void onNewFrameBatch(FrameBatch frameBatch) {
        Gson gson = new Gson();
        String framesStr = gson.toJson(frameBatch.getFrames());
        Map<String, Object> params = new HashMap<>();
        params.put("frames", framesStr);
        params.put("metadata", frameBatch.getMetadata());
        params.put("label", "video");

        String jsonToBeUploaded = gson.toJson(map);
        // upload frame batch to server using this api:
        // /ekyc-core/image-file/upload-video-audio-frames/
        YourResponseObject uploadingResult = yourMethodToUploadFrameBatch(jsonToBeUploaded);

        // Keep the id that generated by the SDK corresponding with the one responded from server
        selfieFrameBatchIdsDictionary.put(
            key = frameBatch.getId(),
            value = uploadingResult.fileId
        );
    }

    @Override
    public void onError(TVDetectionError error) {

    }

    @Override
    public void onSuccess(TVDetectionResult result) {
        List<TVSyncFile> faceIds = new ArrayList();
        List<TVGestureImage> gestureFaces = new ArrayList();
        List<TVVideoFile> videoIds = new ArrayList();
        String cusUserId = "1";
        String selfieType = "selfie";
        String authType = "transfer";
        for (TVImageClass face: result.getFaces()) {
          faceIds.add(TVSyncFile.createById(face.getImageId());
        }
        for (TVGestureFace gesture: result.getGestureFaces()) {
          String gestureName = gesture.getGesture();
          List<TVSyncFile> ids = new ArrayList();
          for (TVImageClass img: gesture.getImages()) {
            ids.add(TVSyncFile.createById(img.getImageId()));
          }
          gestureFaces.add(new TVGestureImage(gesture, ids));
        }

        // If frameBatch is uploaded to server by the SDK
        for (String id: result.getLivenessFrameBatchIds()) {
          videoIds.add(TVVideoFile.createById(id));
        }
        // If frameBatch is uploaded to server by the host app
        for (String id : selfieFrameBatchIdsDictionary.values()) {
            videoIds.add(TVVideoFile.createById(id));
        }

        // SDK uploads images to the server and returns the image IDs to the host app
        // call api to verify face authentication
        // /api-docs/face-authentication-api/authenticate/
        yourMethodToCallFaceAuthenticationAPI(
            cusUserId,
            faceIds,
            gestureFaces,
            videoIds,
            selfieType,
            authType
        );
    }

    @Override
    public void onCanceled(){

    }
});

Step 5: Integrate client's backend call TS's backend

Use API directly: Request face authentication
Use Java SDK: Face Auth

Parameters:

paramAndroidiOSother_vendor
auth_typetransfertransfertransfer
selfie_typeflash_16flash_8vendor_a

client_transaction_id is your transaction ID to identify for reconciling or tracing between 2 systems

Sample code

Java
String cusUserID = "c1b3b3b3-1b3b-4b3b-8b3b-3b3b3b3b3b3b"; // Required
String authType = TVFaceAuthAuthTypeConstant.TRANSFER;
String selfieType ="flash_16";// "flash_16" for android, "flash_8" for iOS, the value should get from SDK.

String clientTransactionID = "a9c9a80a-8ae8-4de9-8dab-d85a85d1882e"; // your transaction ID to identify for reconciling or tracing between 2 systems

List<TVSyncImage> imagesFaceAuth = Arrays.asList(
        TVSyncImage.createById("3e2693e7-1e8f-40f0-be68-2cf73b09c61b"),
        TVSyncImage.createById("36dc7bd6-ed04-4bd3-bd32-61cb9ac4837c"),
        TVSyncImage.createById("15b0db75-d238-4a4b-bea9-4897c7af0a08"),
        TVSyncImage.createById("d8c330d4-5c7a-4f8e-a0f0-44efffb0cfc6"));
List<TVGestureImages> gestureImagesFaceAuth = Arrays.asList(
        new TVGestureImages("right", Arrays.asList(TVSyncImage.createById("99bbe3b5-23e8-41d6-a496-956d7e5c3ed5"))),
        new TVGestureImages("down", Arrays.asList(TVSyncImage.createById("fe140383-81ff-47e3-930f-154272e7da6c"))),
        new TVGestureImages("left", Arrays.asList(TVSyncImage.createById("dd553b55-5b02-48e3-b2bf-ecfa45c9119b")))
        );
List<TVSyncVideo> videos = Arrays.asList(
  TVSyncVideo.createById("dfb4a246-09df-42fc-be41-0faafc8dc5bc")
);

TVResponseData<TVFaceAuthenResponse> faceAuthResponse = TVApi.getInstance().faceAuthen(faceAuthRequest,"", headers);
if (faceAuthResponse.hasErrors()) {
    List<TVApiError> errors = faceAuthResponse.getErrors();
    System.out.println("Face Auth error:" + errors.get(0).getMessage());
} else {
    System.out.println("Face Auth successful");
}


II.2 Hybrid: Share APIs called for both SDK and client's backend.

There are some APIs called from SDK. There are some APIs called from the client's backend. Reference Scenario Scenario Hybrid

Step 1: Create temporary credentials with a verified session token.

Use API directly: Create temporary credential
Use Java SDK: Create temporary credentials

Sample code

// Create temporary credentials
int durationInSeconds = 900;
String transactionID = "";
String xRequestID = "";
String xRequestID2 = "";
Map<String, String> headers = new HashMap<String, String>();
headers.put("X-Request-Id", xRequestID);
headers.put("X-Request-Id2", xRequestID2);
TVTemporaryCredentialRequest request = new TVTemporaryCredentialRequest(durationInSeconds);
TVResponseData<TVTemporaryCredentialResponse> response = TVApi.getInstance().createTemporaryCredential(request, transactionID, headers);
System.out.println("TVTemporaryCredentialResponse: " + GsonUtils.toJson(response));
if (response.hasErrors()) {
    List<TVApiError> errors = response.getErrors();
    System.out.println("Create temporary credentials error:" + errors.get(0).getMessage());
} else {
    System.out.println("Create temporary credentials successful");
}

Secure X-Request-ID2 to return SDK

Use Java SDK: Reference

Return Mobile values to init SDK

propsdescription
x-request-idAPI reconciliation. Reference
x-request-id2Hash(x-request-id2). Reference
access_keythe value from API temporary credentials. Reference
secret_keythe value from API temporary credentials. Reference
face_auth_endpointthe value from TS's administrator

Step 2: Init SDK with temporary credential from Step 1

Android: Init SDK
iOS: Init SDK

Parameters:

The flowId parameter is defined for each use-case differently

flowIddescription
face_authenAuthenticate with face for all flows
reset_passwordAuthenticate to reset password flow
loginUse face to replace text password
paymentAuthenticate payment
transferAuthenticate transfer
transfer_type_AAuthenticate transfer type A
transfer_type_BAuthenticate transfer type B
transfer_type_CAuthenticate transfer type C
transfer_type_DAuthenticate transfer type D
...You can define any authentication type based on your business

Other parameters:

parameterdescription
endpointFrom step 1. eg. https://tv-staging.trustingsocial.com/api
accessKeyIdFrom step 1
accessKeySecretFrom step 1
xRequestIdFrom step 1
xRequestId2From step 1

Sample code

TVInitializeConfiguration config = new TVInitializeConfiguration.Build()
    .setEndpoint(endpoint)
    .setAccessKeyId(accessKeyId)
    .setAccessKeySecret(accessKeySecret)
    .setXRequestId(xRequestId)
    .setXRequestId2(xRequestId2)
    .setFlowId(flowId)
    .setLanguageCode(languageCode)
    .setTheme(theme)
    .build();

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    TrustVisionSDK.INSTANCE.init(context, config, new BaseTrustVisionSDK.TVInitializeListener() {
        @Override
        public void onInitSuccess() {
            // Start Face Authen
            // eg. startFaceAuthentication(....)
        }

        @Override
        public void onInitError(@NonNull TVDetectionError error) {
            // Handle errors
        }
    });
}

Step 3: Start face authentication after init SDK successfully.

Android: Start Face Authentication
iOS: Start Face Authentication

Parameters:

paramAndroidiOS
authModeauthMode = TVAuthMode.flash16(selfieConfiguration)method: TVFaceAuthenMethod.flash8

Sample code

TVSelfieConfiguration selfieConfiguration = new TVSelfieConfiguration.Builder()
    .setCameraOption(TVSDKConfiguration.TVCameraOption.FRONT)
    .setEnableSound(false)
    .setLivenessMode(TVLivenessMode.PASSIVE)
    .setEnableVerticalChecking(false)
    .setSkipConfirmScreen(false)
    .setEnableUploadFrames(true)
    .setEnableUploadImages(true)
    .setEnableSanityCheck(false)
    .setEnableVerifyLiveness(false)
    .build();
TVFaceAuthenticationConfiguration configuration = TVFaceAuthenticationConfiguration.builder()
        .setCusUserId("")
        .setAuthType(AuthType.AUTH)
        .setAuthMode(TVAuthMode.flash16(selfieConfiguration))
        .setEnableFaceAuthentication(false)
        .setEnableFaceRegistration(false)
        .build();

TrustVisionSDK.INSTANCE.startFaceAuthentication(activity, configuration, new TVCapturingCallBack() {
    @Override
    public void onNewFrameBatch(FrameBatch frameBatch) {
    }

    @Override
    public void onError(TVDetectionError error) {
    }

    @Override
    public void onSuccess(TVDetectionResult result) {
    }

    @Override
    public void onCanceled(){
    }
});

Step 4: Mobile App receives result images ID, frames videos ID from SDK

Android: Handle results from SDK
iOS: Handle results from SDK

Sample code

TrustVisionSDK.INSTANCE.startFaceAuthentication(activity, configuration, new TVCapturingCallBack() {
    @Override
    public void onError(TVDetectionError error) {

    }

    @Override
    public void onSuccess(TVDetectionResult result) {
        List<TVSyncFile> faceIds = new ArrayList();
        List<TVGestureImage> gestureFaces = new ArrayList();
        List<TVVideoFile> videoIds = new ArrayList();
        String cusUserId = "1";
        String selfieType = "selfie";
        String authType = "transfer";
        for (TVImageClass face: result.getFaces()) {
          faceIds.add(TVSyncFile.createById(face.getImageId());
        }
        for (TVGestureFace gesture: result.getGestureFaces()) {
          String gestureName = gesture.getGesture();
          List<TVSyncFile> ids = new ArrayList();
          for (TVImageClass img: gesture.getImages()) {
            ids.add(TVSyncFile.createById(img.getImageId()));
          }
          gestureFaces.add(new TVGestureImage(gesture, ids));
        }
        for (String id: result.getLivenessFrameBatchIds()) {
          videoIds.add(TVVideoFile.createById(id));
        }

        // SDK uploads images to the server and returns the image IDs to the host app
        // call api to verify face authentication
        // /api-docs/face-authentication-api/authenticate/
        yourMethodToCallFaceAuthenticationAPI(
            cusUserId,
            faceIds,
            gestureFaces,
            videoIds,
            selfieType,
            authType
        );
    }

    @Override
    public void onCanceled(){

    }
});

Step 5: Integrate client's backend call TS's backend

Use API directly: Request face authentication
Use Java SDK: Face Auth

Parameters:

paramAndroidiOSother_vendor
auth_typetransfertransfertransfer
selfie_typeflash_16flash_8vendor_a

client_transaction_id is your transaction ID to identify for reconciling or tracing between 2 systems

Sample code

Java
String cusUserID = "c1b3b3b3-1b3b-4b3b-8b3b-3b3b3b3b3b3b"; // Required
String authType = TVFaceAuthAuthTypeConstant.TRANSFER;
String selfieType ="flash_16";// "flash_16" for android, "flash_8" for iOS, the value should get from SDK.

String clientTransactionID = "a9c9a80a-8ae8-4de9-8dab-d85a85d1882e"; // your transaction ID to identify for reconciling or tracing between 2 systems

List<TVSyncImage> imagesFaceAuth = Arrays.asList(
        TVSyncImage.createById("3e2693e7-1e8f-40f0-be68-2cf73b09c61b"),
        TVSyncImage.createById("36dc7bd6-ed04-4bd3-bd32-61cb9ac4837c"),
        TVSyncImage.createById("15b0db75-d238-4a4b-bea9-4897c7af0a08"),
        TVSyncImage.createById("d8c330d4-5c7a-4f8e-a0f0-44efffb0cfc6"));
List<TVGestureImages> gestureImagesFaceAuth = Arrays.asList(
        new TVGestureImages("right", Arrays.asList(TVSyncImage.createById("99bbe3b5-23e8-41d6-a496-956d7e5c3ed5"))),
        new TVGestureImages("down", Arrays.asList(TVSyncImage.createById("fe140383-81ff-47e3-930f-154272e7da6c"))),
        new TVGestureImages("left", Arrays.asList(TVSyncImage.createById("dd553b55-5b02-48e3-b2bf-ecfa45c9119b")))
        );
List<TVSyncVideo> videos = Arrays.asList(
  TVSyncVideo.createById("dfb4a246-09df-42fc-be41-0faafc8dc5bc")
);

TVResponseData<TVFaceAuthenResponse> faceAuthResponse = TVApi.getInstance().faceAuthen(faceAuthRequest,"", headers);
if (faceAuthResponse.hasErrors()) {
    List<TVApiError> errors = faceAuthResponse.getErrors();
    System.out.println("Face Auth error:" + errors.get(0).getMessage());
} else {
    System.out.println("Face Auth successful");
}


If the client allows calls API Face Authen from SDK. The client's backend calls API to cross-check the result.

Use API directly: Get result of the request

Sample code

curl -X GET \
https://tv-staging.trustingsocial.com/api/v1/requests_by_req_id/a4facba3-334b-41fb-97e3-4766cb70ae29 \
-H 'Authorization: TV <YOUR ACCESS KEY>:<CREATED SIGNATURE>' \
-H 'X-TV-Timestamp: 2019-04-21T18:00:15+07:00' \
-H 'Content-Type: application/json'

Sample response

JSON
{
    "data": {
        "status": "success",
        "auth_check": {
            "score": 0.9999999862517992,
            "result": "matched"
        },
        "request_id": "cfc7b8d5-f2e2-437b-80e5-d600dfad26e2",
        "user_metadata": {
            "key1": "value1",
            "key2": 2
        },
        "validate_faces_result": {
            "sanity_verdict": "good",
            "is_live": true,
            "sanity_check": {
                "portrait_sanity": {
                    "score": 1,
                    "verdict": "good"
                },
                "request_id": "9f89377f-4bb4-4ecb-884c-f46f1d7d6099",
                "status": "success"
            },
            "liveness_check": {
                "images": null,
                "is_live": true,
                "request_id": "baee3d03-8af4-421b-8968-a0f6172b4df8",
                "score": 1,
                "status": "success"
            }
        },
        "auth_id": "d4f99f9b-4862-437f-a9c9-608e050d06c6",
        "histories": [
            {
                "id": "f1ca6795-cbd4-4eec-821f-b4ac646db627",
                "client_id": "0ef0f7e9-7f2f-4767-84b8-f76da7701c46",
                "cus_user_id": "3b4bf7b6-088b-4931-9279-9259f5c34fe3",
                "face_auth_id": "887249dc-681c-4231-aff9-67734833aca7",
                "id_card_face_id": "4f959f4a-f5de-4b50-8724-224e709d06c2",
                "live_face_id": "009161c9-9c89-4573-8119-8f513de4449c",
                "created_at": "2023-12-27T03:33:06.307977Z",
                "auth_action": "login",
                "status": "success",
                "result": "",
                "face_type": "selfie"
            },
            {
                "id": "8c23af95-aaa0-4448-bfba-68acce31236e",
                "client_id": "0ef0f7e9-7f2f-4767-84b8-f76da7701c46",
                "cus_user_id": "3b4bf7b6-088b-4931-9279-9259f5c34fe3",
                "face_auth_id": "",
                "id_card_face_id": "4f959f4a-f5de-4b50-8724-224e709d06c2",
                "live_face_id": "009161c9-9c89-4573-8119-8f513de4449c",
                "created_at": "2023-12-21T07:24:19.829484Z",
                "auth_action": "login",
                "status": "failure",
                "result": "image is not liveness",
                "face_type": "id_card"
            }
        ]
    }
}