> For the complete documentation index, see [llms.txt](https://docs.caf.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.caf.io/caf-sdk/android/standalone-modules/faceliveness.md).

# Face Liveness (DEPRECATED)

## Current Version

| Name           | Version |
| -------------- | ------- |
| `FaceLiveness` | 5.2.0   |

## Requirements

* Minimum Android SDK API version: `minSdk 26` (Android 8 Oreo)
* Android SDK API version to compile: `compileSdk 34`

To publish your app on the *Google Play Store*, you must complete a data safety form. Since we integrate with the *FingerPrintJS SDK*, you'll need to provide the following information:

| Question in Google Play Console's data safety form                  | Response                                    |
| ------------------------------------------------------------------- | ------------------------------------------- |
| Does your app collect or share any of the required user data types? | Yes.                                        |
| What type of data is collected?                                     | Device or other identifiers.                |
| Is this data collected, shared, or both?                            | Collected.                                  |
| Is this data processed ephemerally?                                 | Yes.                                        |
| Why is this user data collected?                                    | Fraud Prevention, Security, and Compliance. |

{% hint style="warning" %}
`versionName` and `versionCode` are mandatory for the SDK to work correctly.
{% endhint %}

## SDK Dependencies

FaceLiveness leverages the following external SDKs:

| SDK                         | Version |
| --------------------------- | ------- |
| `iProov Biometrics Android` | 11.1.0  |
| `Fingerprint Pro Android`   | 2.7.0   |

* [iProov Biometrics Android](https://github.com/iProov/android): Enables the integration of live facial verification technology.
* [Fingerprint Pro Android](https://github.com/fingerprintjs/fingerprintjs-pro-android-demo): Provides fingerprint authentication capabilities to enhance security features in your app.

These dependencies are easily managed through Gradle and are bundled with the SDK for ease of installation.

### Runtime permissions

| Permission | Reason                                                    | Required |
| ---------- | --------------------------------------------------------- | -------- |
| `CAMERA`   | Capturing the selfie in live facial verification policies | Yes      |

### Installation

If your version of Gradle is earlier than 7, add these lines to your `build.gradle`.

```groovy
allprojects {
  repositories {
  ...
  maven { url 'https://repo.combateafraude.com/android/release' }
  maven { url 'https://raw.githubusercontent.com/iProov/android/master/maven/' }
  maven { url 'https://maven.fpregistry.io/releases' }
  maven { url 'https://jitpack.io' }

}}
```

If your version of Gradle is 7 or newer, add these lines to your `settings.gradle`.

```groovy
dependencyResolutionManagement {
    repositories {
        ...
        maven { url 'https://repo.combateafraude.com/android/release' }
        maven { url 'https://raw.githubusercontent.com/iProov/android/master/maven/' }
        maven { url 'https://maven.fpregistry.io/releases' }
        maven { url 'https://jitpack.io' }
    }
}
```

Add support for Java 8 to your `build.gradle` file. Skip this step if Java 8 is enabled.

```groovy
android {
    ...
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}
```

Add the SDK version to the dependencies section in your `build.gradle` file

```groovy
dependencies {
    implementation 'io.caf.sdk:new-face-liveness:{version}'
}
```

## Instantiating the SDK

First, create an object of type `FaceLiveness`. This object is for you to configure all your business rules:

```java
FaceLiveness faceLiveness = new FaceLiveness.Builder(String mobileToken)
    //see table below
    .build();
```

### Builder method

| Parameter                                                                                                                                                                                                                                                                                                                             | Required                                   |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------ |
| <p><code>String mobileToken</code></p><p>Usage token associated with your Identity account (see how to get it <a href="https://github.com/combateafraude/public-docs/blob/docs-sdks/android/standalone-modules/faceliveness/broken-reference/README.md">here</a>).</p>                                                                | Yes                                        |
| <p><code>.setStage(CAFStage stage)</code></p><p>Used to redirect the SDK to the desired stage in caf api. The method takes as parameter an enum <code>CafStage</code> to select the environment:</p><ul><li><code>CAFStage.PROD</code> set production environment.</li><li><code>CAFStage.BETA</code> set beta environment.</li></ul> | No. The default is `CAFStage.PROD`         |
| <p><code>.setFilter(Filter filter)</code></p><p>Used to change the SDK filter, that has the following options:</p><ul><li><code>Filter.NATURAL</code></li><li><code>Filter.LINE\_DRAWING</code></li></ul>                                                                                                                             | No, the default is `LINE_DRAWING`          |
| <p><code>.setEnableScreenshots(boolean bool)</code></p><p>Used to enable screenshots during the SDK scan. Disabled by default for security reasons.</p>                                                                                                                                                                               | No, the default is `false`                 |
| <p><code>.setLoadingScreen(boolean bool)</code></p><p>Used to enable a default loading progressbar during loading events. You can set your customized loading screen instead, using the <code>onLoading</code> method below.</p>                                                                                                      | No, the default is `false`                 |
| <p><code>.setImageUrlExpirationTime(Time time)</code></p><p>Used to customize the image URL expiration time, that has the following options:</p><ul><li><code>Time.THREE\_HOURS</code></li><li><code>Time.THIRTY\_DAYS</code></li></ul>                                                                                               | No, the default is `null`                  |
| <p><code>.setFaceLivenessBaseUrl(String baseURL)</code></p><p>Used to enable the use of reverse proxy to execute face liveness. If used, the certificates must be set with the setCertificates method.</p>                                                                                                                            | No, the default is the original IProov URL |
| <p><code>.setCertificates(String\[] certificates)</code></p><p>Used to set pinned certificates for reverse proxy implementation.</p>                                                                                                                                                                                                  | No, the default is an empty list           |
| <p><code>.setAuthenticationBaseUrl(String baseURL)</code></p><p>Used to enable the use of reverse proxy to execute SDK's authentications.</p>                                                                                                                                                                                         | No, the default is the original Caf's URL  |

## Reverse proxy

In order to implement reverse proxy settings, you must follow these instructions:

### FaceLiveness reverse proxy

* Set your proxy to communicate with \`wss\://us.rp.secure.iproov.me/ws´.
* Use the method `.setFaceLivenessBaseUrl` to set the URL on which the FaceLiveness must run.
  * **The URL's protocol must be WSS.**
* Use the method `.setCertificates` method to set the certificates, which are base64-encoded SHA-256 hash of certificate' Subject Public Key Info.
  * **Certificates are needed in order to make Faceliveness reverse proxy work.**

```java
FaceLiveness faceLiveness = new FaceLiveness.Builder(usersToken)
        .setFaceLivenessBaseUrl("wss://my.proxy.io/ws/")
        .setCertificates(new String[]{
                "4d69f16113bed7d62ca56feb68d32a0fcb7293d3960=",
                "50f71c5dda30741ee4be1ac378e12539b0d1d511f99=",
                "9f85e26c1ae41f7ac97adc4099be7f2a40759510ab9="
        })
        .build();
```

### Authentication reverse proxy

* Set your proxy to communicate with the URL that corresponds the CAFStage you are using:
  * CAFStage.PROD -> <https://api.public.caf.io/v1/sdks/faces/>
  * CAFStage.BETA -> <https://api.public.beta.caf.io/v1/sdks/faces/>
  * CAFStage.DEV -> <https://api.public.dev.caf.io/v1/sdks/faces/>
* Use the method `.setAuthenticationBaseUrl` to set the URL on which the authorization requests must run.
  * **The URL's protocol must be HTTPS.**

```java
FaceLiveness faceLiveness = new FaceLiveness.Builder(usersToken)
        .setAuthenticationBaseUrl("https://my.proxy.io/v1/faces/")
        .build();
```

## Consulting a policy

To authenticate a user, use the `.startSDK()` method. You must enter the `personId`, your app's Context and a `VerifyLivenessListener` object.

### Parameters

| Parameter                                                                                                                                                                                                                                                               | Required |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| <p><code>String personId</code></p><p>Identifier of the user who will perform the face liveness verification. It's recommended to use the user's identification document in this field, such as their CPF (Brazilian document ID), but it could be any other value.</p> | Yes      |
| <p><code>Context context</code></p><p>Your app Context</p>                                                                                                                                                                                                              | Yes      |
| <p><code>VerifyLivenessListener listener</code></p><p>Response Listener</p>                                                                                                                                                                                             | Yes      |

### Example

```java
faceLiveness.startSDK(Context context, String personId, new VerifyLivenessListener() {
    @Override
    public void onSuccess(FaceLivenessResult result) {

    }

    @Override
    public void onFailure(FaceLivenessFailureResult result) {

    }

    @Override
    public void onError(SDKError sdkerror) {

    }

    @Override
    public void onCancel() {

    }

    @Override
    public void onLoading() {

    }

    @Override
    public void onLoaded() {

    }
});
```

### VerifyLivenessListener options

| Method      | Description                                                                                                                           |
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `onSuccess` | The execution has ended with success, you have to use the `faceLivenessResult` and check for the results of the SDK.                  |
| `onFailure` | The execution has ended with failure, you have to use the `faceLivenessFailureResult` and check for the results of the SDK.           |
| `onError`   | The execution has ended with error, you have to use the `sdkFailure` and check for the error results of the SDK.                      |
| `onCancel`  | The execution has been cancelled by the user.                                                                                         |
| `onLoading` | The SDK is loading, you can use this method to set a action in your app, for example a loading.                                       |
| `onLoaded`  | The SDK is not loading anymore, you can use this method to set a action in your app, for example, you can stop your previous loading. |

## SDK Results

### Success cases

At the end of a successful execution, you will receive an object of type [FaceLivenessResult](#facelivenessresult). This object carries a `signedResponse` property containing a JWT token with the execution result. This token should be decrypted to obtain the execution results details.

```java
  livenessResult.getSignedResponse()
```

#### FaceLivenessResult (Class)

| Property                | Description                                                                                                                                                                                                                                                                                                             |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `String signedResponse` | Signed response from the CAF server confirming that the captured selfie has a real face. This parameter is used to get an extra layer of security, checking that the signature of the response is not broken, or caused by request interception. If it is broken, there is a strong indication of request interception. |

#### SignedResponse params

Within the `signedResponse`, the parameter `isAlive` defines the execution of liveness, where `true` is approved and `false` is rejected ([Failure case](#failure-cases) will be returned).

| Event        | Description                                                                            |
| ------------ | -------------------------------------------------------------------------------------- |
| `requestId`  | Request identifier.                                                                    |
| `isAlive`    | Validation of a living person, identifies whether the user passed successfully or not. |
| `token`      | Request token.                                                                         |
| `userId`     | User identifier provided for the request.                                              |
| `imageUrl`   | Temporary link to the image, generated by our API.                                     |
| `personId`   | User identifier provided for the SDK.                                                  |
| `sdkVersion` | Sdk version in use.                                                                    |
| `iat`        | Token expiration.                                                                      |

{% hint style="warning" %}
The **isAlive** parameter is **VERY IMPORTANT**, as it dictates whether the validation process proceeds or halts. When `isAlive: true`, the user gains passage to continue their journey; conversely, if `isAlive: false`, the user is deemed invalid and access to further stages of the journey should be denied. This parameter plays a pivotal role in guiding the flow of operations.
{% endhint %}

### Error cases

In the event of execution errors, you will receive an object of type `SDKError`. This object encompasses an enum containing the `errorType`, and a `description`.

#### SDKError (Class)

| Property              | Description                   |
| --------------------- | ----------------------------- |
| `String description`  | Error description.            |
| `ErrorType errorType` | Return the type of the error. |

#### ErrorType (Enum class)

| Error                                | Description                                                                                                                     |
| ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------- |
| `CAMERA_PERMISSION`                  | Indicates that the device does not have permission to access the camera, either due to user denial or missing app permissions.  |
| `NETWORK_EXCEPTION`                  | Indicates a network-related error, such as no internet connection, server timeouts, or network congestion.                      |
| `SERVER_EXCEPTION`                   | Indicates a server-side error, which may include server misconfigurations, processing failures, or service interruptions.       |
| `TOKEN_EXCEPTION`                    | Indicates an issue with the provided authentication token, such as being invalid, expired, or lacking necessary permissions.    |
| `UNSUPPORTED_DEVICE`                 | Indicates that the device hardware or software does not meet the minimum requirements for facial recognition.                   |
| `MULTI_WINDOW_UNSUPPORTED_EXCEPTION` | Indicates that the user attempted to use facial recognition in split-screen or multi-screen mode, which is not supported.       |
| `CAPTURE_ALREADY_ACTIVE_EXCEPTION`   | Indicates that a facial recognition capture is already in progress. A new capture cannot start until the current one completes. |
| `CAMERA_EXCEPTION`                   | Indicates an error occurred while acquiring or using the camera, typically when using external camera support.                  |
| `FACE_DETECTOR_EXCEPTION`            | Indicates an error occurred with the face detector during the facial recognition process.                                       |
| `UNEXPECTED_ERROR_EXCEPTION`         | Indicates an unrecoverable error occurred during the facial recognition transaction.                                            |
| `INVALID_OPTIONS_EXCEPTION`          | Indicates an error occurred when applying the specified options for facial recognition.                                         |
| `CERTIFICATE_EXCEPTION`              | Indicates that there are no valid certificates for the proxy URL, preventing secure communication.                              |
| `IMAGE_NOT_FOUND_EXCEPTION`          | Indicates that the image that has been captured couldn’t be found to be validated.                                              |
| `TOO_MANY_REQUESTS_EXCEPTION`        | Indicates that the server has received more requests than it’s prepared to handle.                                              |

### Failure cases

In the event of execution failures, you will receive an object of type `SDKFailure`. This object encompasses an enum containing the `failureType`, `description` and a `signedResponse`.

#### FaceLivenessFailureResult (Class)

| Property                | Description                                                                                                                                                                                                                                                                                                             |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `String signedResponse` | Signed response from the CAF server confirming that the captured selfie has a real face. This parameter is used to get an extra layer of security, checking that the signature of the response is not broken, or caused by request interception. If it is broken, there is a strong indication of request interception. |
| `String failureType`    | In case of a specific failure, return the error type.                                                                                                                                                                                                                                                                   |
| `String failureMessage` | In case of a specific failure, return the instructions to avoid the error.                                                                                                                                                                                                                                              |

#### Failure Types

All failure reasons are exclusively returned in GPA liveness validation flows. In LA (Liveness Assurance) flows, any failure will consistently return the generic UNKNOWN error, regardless of the specific issue encountered.

| FailureReason Value | Description (English)                  | LA | GPA |
| ------------------- | -------------------------------------- | -- | --- |
| `UNKNOWN`           | Try again                              | ✅  | ✅   |
| `TOO_MUCH_MOVEMENT` | Keep still                             | ❌  | ✅   |
| `TOO_BRIGHT`        | Move somewhere darker                  | ❌  | ✅   |
| `TOO_DARK`          | Move somewhere brighter                | ❌  | ✅   |
| `MISALIGNED_FACE`   | Keep your face in the oval             | ❌  | ✅   |
| `EYES_CLOSED`       | Keep your eyes open                    | ❌  | ✅   |
| `FACE_TOO_FAR`      | Move your face closer to the screen    | ❌  | ✅   |
| `FACE_TOO_CLOSE`    | Move your face farther from the screen | ❌  | ✅   |
| `SUNGLASSES`        | Remove sunglasses                      | ❌  | ✅   |
| `OBSCURED_FACE`     | Remove any face coverings              | ❌  | ✅   |
| `MULTIPLE_FACES`    | Ensure only one person is visible      | ❌  | ✅   |
| `BACKGROUND_ISSUE`  | Unsuitable background                  | ❌  | ✅   |
| `DEVICE_ISSUE`      | Incompatible device                    | ❌  | ✅   |
| `EYEWEAR`           | Eyewear detected                       | ❌  | ✅   |
| `FACE_NOT_FOUND`    | Face detection failure                 | ❌  | ✅   |
| `FRAMES_BLURRY`     | Blurry frames detected                 | ❌  | ✅   |
| `MOTION_ISSUE`      | Device motion error                    | ❌  | ✅   |
| `LIGHTING_ISSUES`   | Poor lighting conditions               | ❌  | ✅   |
| `REJECTED`          | Transaction rejected                   | ❌  | ✅   |
| `SYSTEM_ERROR`      | Internal system error                  | ❌  | ✅   |
| `TIMEOUT`           | Session timeout                        | ❌  | ✅   |
| `USER_NOT_FOUND`    | User lookup failure                    | ❌  | ✅   |
| `DEVICE_RESTART`    | Device state error                     | ❌  | ✅   |
| `PROCESSING_FAULT`  | Processing error                       | ❌  | ✅   |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.caf.io/caf-sdk/android/standalone-modules/faceliveness.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
