> 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/ios/standalone-modules/faceliveness.md).

# Face Liveness (DEPRECATED)

## Current Version

| Name           | Version |
| -------------- | ------- |
| `FaceLiveness` | 7.4.0   |

### Requirements

| Deployment Info | Version |
| --------------- | ------- |
| iOS Target      | 15.0+   |
| Xcode           | 16.2+   |
| Swift           | 5.5+    |

* A valid [Caf mobileToken](https://github.com/combateafraude/public-docs/blob/docs-sdks/sdk_integration_documentation.md#2-generating-access-tokens).
* Cocoapods installed

### SDK Dependencies

FaceLiveness utilizes two key external SDKs, managed through CocoaPods for straightforward integration:

| SDK              | Version |
| ---------------- | ------- |
| `iProov`         | 13.1.0  |
| `FingerprintPro` | 2.7.0   |

* [iProov Biometrics iOS](https://github.com/iProov/ios): Facilitates the integration of live facial verification technology.
* [FingerprintPro iOS](https://github.com/fingerprintjs/fingerprintjs-pro-ios): Adds fingerprint authentication capabilities, enhancing your app's security features.

### Runtime permissions

In the `info.plist` file, add the permissions below:

| Permission                           | Reason                                                    | Required |
| ------------------------------------ | --------------------------------------------------------- | -------- |
| `Privacy - Camera Usage Description` | Capturing the selfie in live facial verification policies | Yes      |

### Installation

#### CocoaPods

In your Podfile, specify the reference to our framework. Replacing `<version>` with the current [version](#current-version):

```ruby
target 'your-project' do
  use_frameworks!

  pod 'FaceLiveness', '<version>'
```

For versions prior to `FaceLiveness 4.0.0`, you must also include these additional sources in the Podfile:

```ruby
source 'https://github.com/combateafraude/iOS.git'
source 'https://cdn.cocoapods.org/'
```

#### SPM

1. Open your Xcode project.
2. Navigate to **File > Add Packages**.
3. In the search bar, paste the URL of this repository:

```console
https://github.com/combateafraude/FaceLiveness.git
```

## Instantiating the SDK

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

```swift
class FaceLivenessViewController: UIViewController {
    var faceLiveness: FaceLivenessSDK?

    func setupFaceLiveness() {
        faceLiveness = FaceLivenessSDK.Build()
        // the table below shows all the SDK configuration options
        .build()
        faceLiveness?.delegate = self
    }

    func startFaceLiveness() {
        faceLiveness?.startSDK(viewController: self, mobileToken:"yourMobileToken", personId: "personId")
    }
}
```

### FaceLiveness Options

| Parameter                                                                                                                                                                                                                                                                                                                                                                                                                                                                  | Required | Default Value          |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ---------------------- |
| <p><code>.startSDK(viewController: UIViewController, mobileToken: String, personId: String)</code></p><ul><li><code>token</code>: Usage token associated with your CAF account</li><li><code>personId</code>: 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.</li></ul>                      |          |                        |
| <p><code>.setStage(stage: CAFStage)</code></p><p>Used to redirect the SDK to the desired environment in caf api. It has the following options: <code>.beta</code> or <code>.prod</code>.</p>                                                                                                                                                                                                                                                                               | No       | `.prod`                |
| <p><code>.setFilter(filter: Filter)</code></p><p>Set the camera filter applied to the camera preview. It has the following options: <code>.natural</code> or <code>.lineDrawing</code></p>                                                                                                                                                                                                                                                                                 | No       | `.lineDrawing`         |
| <p><code>.setLoadingScreen(withLoading: Bool)</code></p><p>This boolean parameter determines whether the loading screen will be implemented via a delegate or if you will use the default screen. If set to 'true,' the loading screen will be a standard SDK screen. In the case of 'false,' you should use the 'LoadingScreen' session and implement the delegates.</p>                                                                                                  | No       | **false**              |
| <p><code>.setImageUrlExpirationTime(time: Time)</code></p><p>Use to change the default image URL expiration time to retrieve the scan capture. It has the following options: <code>.threeHours</code>, <code>.thirtyDays</code> or <code>.thirtyMin</code>.</p>                                                                                                                                                                                                            | No       | **30 min**             |
| <p><code>.setAuthenticationBaseUrl(authBaseUrl: String)</code></p><p>Enables the use of a reverse proxy to execute SDK's authentications. Sets the base URL for authentication; protocol must be HTTPS. Adds a trailing slash if missing.</p>                                                                                                                                                                                                                              | No       | **Default Caf URL**    |
| <p><code>.setFaceLivenessBaseUrl(livenessBaseUrl: String)</code></p><p>Enables the use of a reverse proxy to execute face liveness checks. Sets the base URL; protocol must be WSS. Adds a trailing slash if missing. Requires certificates set via <code>.setCertificates</code> for security.</p>                                                                                                                                                                        | No       | **Default IProov URL** |
| <p><code>.setCertificates(certificates: \[String])</code></p><p>Sets the SHA256 Base64-encoded protocols for secure communication in reverse proxy implementations. Required when using custom URLs for authentication or face liveness checks.</p>                                                                                                                                                                                                                        | No       | **Empty list**         |
| <p><code>.setCustomLocalization(named: String?)</code></p><p>This method allows you to specify a custom localization resource name for the iProov module. When a name is provided, the SDK will load the matching localization file instead of the default resource bundle. For further details on the localization files format and integration, please refer to the <a href="https://github.com/iProov/ios/wiki/Localization">iProov Localization documentation</a>.</p> | No       | **nil**                |

## Reverse Proxy

To configure reverse proxy settings, please follow these instructions:

### FaceLiveness Reverse Proxy

* Set your proxy to communicate with the URL that corresponds to 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 `.setFaceLivenessBaseUrl` to set the URL on which FaceLiveness should run.
  * **The URL's protocol must be WSS.**
* Use the `.setCertificates` method to set the certificates, which should be the base64-encoded SHA-256 hash of the certificate's Subject Public Key Info.
  * **Certificates are required for the FaceLiveness reverse proxy to work properly.**

```swift
    faceLiveness = FaceLivenessSDK.Build()
    .setFaceLivenessBaseUrl("wss://my.proxy.io/ws/")
    .setCertificates(certificates: [
        "4d69f16113bed7d62ca56feb68d32a0fcb7293d3960=",
        "50f71c5dda30741ee4be1ac378e12539b0d1d511f99=",
        "9f85e26c1ae41f7ac97adc4099be7f2a40759510ab9="
    ])
    .build()
```

### Authentication reverse proxy

* Set your proxy to communicate with \`wss\://us.rp.secure.iproov.me/ws´.
* Use the method `.setAuthenticationBaseUrl` to set the URL on which the authorization requests must run.
  * **The URL's protocol must be HTTPS.**

```swift
    faceLiveness = FaceLivenessSDK.Build()
        .setAuthenticationBaseUrl("https://my.proxy.io/v1/faces/")
        .build();
```

## Getting the Results

You must implement the `FaceLivenessDelegate` class to get the SDK results. To do that, you should provide a `UIViewController` to your SDK instance:

```swift
faceLiveness?.delegate = self
```

### Delegate Implementation

The delegate below must be implemented to handle the SDK results.\
When implementing the delegate extension, you will have access to an object depending on the return type. In each case, the object carries different information.

```swift
extension FaceLivenessViewController: FaceLivenessDelegate {
    func didFinishLiveness(with livenessResult: FaceLiveness.LivenessResult) {
        //handle success result
    }
    
    func didFinishWithError(with sdkError: FaceLiveness.SDKError) {
        //handle error result
    }

    func didFinishWithFailure(with sdkFailure: FaceLiveness.SDKFailure) {
        //handle failure result
    }
    
    func didFinishWithCancelled() {
        //handle when user closes the SDK
    }
    
    func onConnectionChanged(_ state: FaceLiveness.LivenessState) {
        //handle loading screen display
    }
}
```

### Loading Screen

To create a loading screen during the SDK validation processes, you need to implement a view with the loading screen and display this screen in the `onConnectionChanged(_ state: FaceLiveness.LivenessState)` delegate function.

| state      | description                                     | loading screen |
| ---------- | ----------------------------------------------- | -------------- |
| closed     | SDK has been closed                             | dismiss        |
| connecting | SDK is connecting to liveness server            | display        |
| connected  | SDK has been connected with the liveness server | dismiss        |

In the SDK implementation, it is necessary to add the view to the view stack using the following code. This makes the view visible.

```swift
  view.addSubview(loadingHUD)
```

This view should be added before the Builder of each SDK.

## SDK Results

### Success cases

At the end of a successful execution, you will receive an object of type `LivenessResult`. 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.

```swift
  livenessResult.signedResponse
```

#### LivenessResult (Struct)

| Property                  | Description                                                                                                                                                                                                                                                                                                             |
| ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `signedResponse: String?` | 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 (Struct)

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

#### ErrorType (Enum)

| ErrorType                       | Description                                                                                                                     |
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `unsupportedDevice`             | Indicates that the device hardware or software does not meet the minimum requirements for facial recognition.                   |
| `cameraPermission`              | Indicates that the device does not have permission to access the camera, either due to user denial or missing app permissions.  |
| `networkException`              | Indicates a network-related error, such as no internet connection, server timeouts, or network congestion.                      |
| `tokenException`                | Indicates an issue with the provided authentication token, such as being invalid, expired, or lacking necessary permissions.    |
| `serverException`               | Indicates a server-side error, which may include server misconfigurations, processing failures, or service interruptions.       |
| `certificateException`          | Indicates that there are no valid certificates for the proxy URL, preventing secure communication.                              |
| `captureAlreadyActiveException` | Indicates that a facial recognition capture is already in progress. A new capture cannot start until the current one completes. |
| `unexpectedErrorException`      | Indicates an unrecoverable error occurred during the facial recognition transaction.                                            |
| `userTimeoutException`          | Indicates a server-side error, which may include server misconfigurations, processing failures, or service interruptions.       |
| `imageNotFoundException`        | Indicates a user has taken too long to complete the claim.                                                                      |
| `tooManyRequestsException`      | 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`.

#### SDKFailure (Class)

| Property                 | Description                                                                                                                                                                                                                                                                                                             |
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `signedResponse String?` | 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. |
| `failureType String?`    | In case of a specific failure, return the error type.                                                                                                                                                                                                                                                                   |
| `failureMessage String?` | 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.

| FailureType       | Description                             | LA | GPA |
| ----------------- | --------------------------------------- | -- | --- |
| `unknown`         | Try again.                              | ✅  | ✅   |
| `tooMuchMovement` | Keep still.                             | ❌  | ✅   |
| `tooBright`       | Move somewhere darker.                  | ❌  | ✅   |
| `tooDark`         | Move somewhere brighter.                | ❌  | ✅   |
| `misalignedFace`  | Keep your face in the oval.             | ❌  | ✅   |
| `eyesClosed`      | Keep your eyes open.                    | ❌  | ✅   |
| `faceTooFar`      | Move your face closer to the screen.    | ❌  | ✅   |
| `faceTooClose`    | Move your face farther from the screen. | ❌  | ✅   |
| `sunglasses`      | Remove sunglasses.                      | ❌  | ✅   |
| `obscuredFace`    | Remove any face coverings.              | ❌  | ✅   |
| `multipleFaces`   | Ensure only one person is visible.      | ❌  | ✅   |

### ⚠️ Sandbox Configuration for iOS

If you encounter the error related to `Sandbox: rsync.samba deny file-write-create` when using this SDK in an iOS project, follow the steps below:

1. In Xcode, go to your project under the Build Settings tab.
2. In the search field, look for sandbox.
3. Locate the User Script Sandboxing option.
4. Change the value to No.


---

# 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/ios/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.
