# Face Login (iOS)

The Face Login module performs face authentication to allow users to log in without a password or token.

## Supported Platforms

- iOS

## How It Works

Face Login uses biometric face scanning to authenticate users without passwords or tokens. When a user initiates a login, the SDK captures a selfie and runs liveness detection to confirm the person is physically present and not a spoofed image or recording.

There are two authentication modes:

- **1:N (Identify)**: The captured face is compared against your entire database of approved users. The system finds the closest match and returns that user's identity. If multiple similar faces are detected, the system performs step-up authentication, prompting the user to confirm their identity with an additional code. Use this mode when you do not know in advance who is trying to log in.
- **1:1 (Verify)**: The captured face is compared against a single, pre-specified user identified by their [customer UUID](https://developer.incode.com/docs/glossary#customer-uuid). The system returns a pass or fail for that specific person only. Use this mode when the user has already been identified by another means and you only need to confirm they are physically present.

In both modes, if liveness detection fails, the result is flagged as a spoof attempt rather than a failed face match, allowing your application to handle the two cases differently.

## Prerequisites

- The user must have completed a full Incode onboarding flow and be an approved customer.

## Integrate Face Login Module

### Initialize the IncdOnboarding SDK

Add the following line of code to your `AppDelegate` class:

```
IncdOnboardingManager.shared.initIncdOnboarding(url: url, apiKey: apiKey)
```

Incode provides `url` and `apiKey`. If you are running the app on a simulator, set the `testMode` parameter to `true`.

### Execute 1:N Face Login: Identify a User

Call `startFaceLogin` without a `customerUUID` to match against your full user database:

```swift
IncdOnboardingManager.shared.presentingViewController = self
IncdOnboardingManager.shared.startFaceLogin() { result in
          guard let loginResult = result.faceLoginResult else {
            // An error occurred
            print(result.error)
            return
          }
          
          if loginResult.success == true {
            // Face authentication successful
            let customerUUID = loginResult.customerUUID
            let token = loginResult.token
            let interviewId = loginResult.interviewId
          } else {
            if result.spoofAttempt == true {
              // Liveness check  failed
            } else {
              // No matching face found in database
            }
          }
        }
```

### Execute 1:1 Face Login: Verify a Specific User

Call `startFaceLogin` with the `customerUUID` of the user you want to verify:

```swift
IncdOnboardingManager.shared.presentingViewController = self
IncdOnboardingManager.shared.startFaceLogin(customerUUID: "YOUR_CUSTOMER_ID") { result in
          guard let loginResult = result.faceLoginResult else {
            // An error occurred
            print(result.error)
            return
          }
          
          if loginResult.success == true {
            // Face authentication successful
            let customerUUID = loginResult.customerUUID
            let token = loginResult.token
            let interviewId = loginResult.interviewId
          } else {
            if result.spoofAttempt == true {
              // Liveness check failed
            } else {
              // User's face did not match
            }
          }
        }
```

### View Face Login Result

The callback returns a `SelfieScanResult` object with the following fields:

- `faceLoginResult`: A `FaceLoginResult` object that contains:
  - `success`: `true` if face login was successful; `false` if it was not.
  - `customerUUID`: The customer UUID of the matched user; `nil` if no match was found.
  - `token`: The customer token of the matched user; `nil` if no match was found.
  - `interviewId`: The session [interviewId](https://developer.incode.com/docs/glossary#interviewid) from the user's original approval flow.
  - `interviewToken`: The session [interviewToken](https://developer.incode.com/docs/glossary#session-token) used during user approval.
  - `transactionId`: The transaction ID of the face login attempt.
- `spoofAttempt`: `true` if the attempt was flagged as a spoof; `false` if it was not.
- `image`: The selfie image captured during the scan.
- `error`: A `SelfieScanError` describing any error that occurred.

### Specify Login Parameters

By default, Face Login performs liveness detection and face matching on the server. For faster authentication and reduced network dependency, switch to on-device processing using the `faceAuthMode` parameter:

- To use on-device liveness detection with server-side face matching, specify `FaceAuthMode.hybrid` via the `faceAuthMode` param of the `startFaceLogin` method:
  ```swift
  IncdOnboardingManager.shared.presentingViewController = self
  IncdOnboardingManager.shared.startFaceLogin(faceAuthMode: .hybrid) { result in
            ...
          }
  ```
- To use on-device liveness detection and on-device face matching, specify `FaceAuthMode.local` via the `faceAuthMode` param of the `startFaceLogin` method:
  ```swift
  IncdOnboardingManager.shared.presentingViewController = self
  IncdOnboardingManager.shared.startFaceLogin(faceAuthMode: .local) { result in
            ...
          }
  ```

<Callout icon="📘" theme="info">
  ### Note

  `FaceAuthMode.hybrid` and `FaceAuthMode.local` require specific Onboarding SDK frameworks with FaceAuth models included. If using CocoaPods, specify the `l` variant: for example, `5.5.0-d-l`.
</Callout>

The following additional parameters are available on `startFaceLogin`:

| Parameter                  | Type    | Default | Description                                                                                                                                                       |
| -------------------------- | ------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `showTutorials`            | Boolean | `true`  | Shows a tutorial screen before the selfie scan.                                                                                                                   |
| `faceAuthModeFallback`     | Boolean |         | When `true`, falls back to `FaceAuthMode.server` if `FaceAuthMode.local` cannot run due to a missing face template on the device. Applies to 1:1 Face Login only. |
| `lensesCheck`              | Boolean | `true`  | Detects whether the user is wearing lenses during the selfie scan. Set to `false` to disable.                                                                     |
| `faceMaskCheck`            | Boolean | `false` | Detects whether the user is wearing a face mask during capture. Set to `true` to enable.                                                                          |
| `logAuthenticationEnabled` | Boolean | `true`  | Sends liveness statistics after each login attempt. Set to `false` to disable.                                                                                    |
| `customLogo`               | Image   |         | A custom logo to display during face capture. Uses the default Incode logo if not specified.                                                                      |

### Manage Locally Stored Identities

To authenticate multiple users using 1:N mode with `FaceAuhtMode.local`, you must populate a local database of user identities on the device. You can use the following methods to manage that database.

**Add a Face**

To add a single identity to the local database, use the `addFace` method and provide a `FaceInfo` object that contains the following fields:

| Field          | Type   | Description                                                                                    |
| -------------- | ------ | ---------------------------------------------------------------------------------------------- |
| `faceTemplate` | String | The biometric representation of the user's face.                                               |
| `customerUUID` | String | The user's unique customer identifier in Incode's database.                                    |
| `templateId`   | String | The unique identifier of the biometric representation of the user's face in Incode's database. |

```swift
let face = FaceInfo(faceTemplate: template,
                    customerUUID: uuid,
                    templateId: templateId)
IncdOnboardingManager.shared.addFace(face)
```

**Remove a Face**

To remove a single identity from the local database, use the `removeFace` method and provide a `customerUUID`:

```swift
IncdOnboardingManager.shared.removeFace(customerUUID: customerUUID)
```

**Get Faces**

To fetch all identities currently stored in the local database, use the `getFaces` method:

```swift
  var identities: [FaceInfo] = IncdOnboardingManager.shared.getFaces()
```

**Set Multiple Faces**

To replace the entire local database with a new list of identities, use the `setFaces` method and provide a list of `FaceInfo` objects:

```swift
IncdOnboardingManager.shared.setFaces(faceInfoList)
```

<Callout icon="⚠️" theme="warn">
  ### Warning

  This method deletes all existing entries before the new list is written.
</Callout>

**Clear the Face Database**

To remove all identities from the local database, use the `setFaces` method and provide an empty list of `FaceInfo `objects:

```
IncdOnboardingManager.shared.setFaces([])
```

<br />
