# Face Login

Face Login authenticates a user by performing a face match between a captured selfie and a previously enrolled face. The SDK supports two authentication modes: **1:1**, which matches against a specific user identified by `customerUUID`, and **1:N**, which performs a database lookup to find a match.

## Prerequisites

- The SDK is initialized. See [Installation](./flutter-installation).
- The user has an approved account with an enrolled face.

Enrollment happens as a byproduct of a standard onboarding flow that includes the `FaceMatch` module. Alternatively, an admin can enroll a user by clicking **Add face to Database** in Dashboard.

## Face Login 1:1

1:1 Face Login performs a face comparison between the captured selfie and the face on file for a specific user, identified by their `customerUUID`. Returns a successful match if the faces match.

Use 1:1 when you already know which user is attempting to authenticate (for example, the user has logged in with a username or email first).

If the user was approved during onboarding on a mobile device, the `customerUUID` is returned as part of the [Approve module result](./flutter-results#approve).

```dart
IncodeOnboardingSdk.startFaceLogin(
  faceLogin: FaceLogin(customerUUID: "yourCustomerUUID"),
  onSuccess: (FaceLoginResult result) {
    print(result);
  },
  onError: (String error) {
    print(error);
  },
);
```

## Face Login 1:N

1:N Face Login performs a database lookup across all of your enrolled users and returns a successful match if the captured face is found.

Use 1:N when you don't know which user is attempting to authenticate (for example, passwordless sign-in flows).

```dart
IncodeOnboardingSdk.startFaceLogin(
  faceLogin: FaceLogin(),
  onSuccess: (FaceLoginResult result) {
    print(result);
  },
  onError: (String error) {
    print(error);
  },
);
```

## FaceLoginResult

`FaceLoginResult` contains the following fields:

- `image`: Selfie image captured during login.
- `spoofAttempt`: bool. `true` indicates the user tried to spoof the system (using a photo, screen, or other method). `false` indicates a real person.
- `base64Images`: Base64 representations of the selfie image.
- `faceMatched`: bool. `true` if the faces matched, `false` otherwise.
- `customerUUID`: String?. Unique user identifier if authentication succeeded. `null` if `faceMatched` is `false`.
- `interviewId`: String. Session ID in which the user was approved.
- `interviewToken`: String. Session token in which the user was approved.
- `token`: String. Token that can be used for further API calls.
- `transactionId`: String. Unique identifier of the Face Login attempt.
- `hasLenses`: bool. Indicator if the login attempt failed because the user was wearing lenses.
- `hasFaceMask`: bool. Indicator if the login attempt failed because the user was wearing a face mask.

## Configuration

Configure Face Login behavior by passing parameters to the `FaceLogin` object.

### Authentication modes

By default, Face Login performs spoof and face recognition checks on Incode's servers.

To perform both checks locally on the device, set `faceAuthMode` to `FaceAuthMode.local`. Local authentication enables offline use, but requires that the user was originally onboarded and approved on the same device.

```dart
FaceLogin faceLogin = FaceLogin(
  customerUUID: "yourCustomerUUID",
  faceAuthMode: FaceAuthMode.local,
);
```

To use `FaceAuthMode.local` on Android, add the following dependencies to your `app/build.gradle`:

- `com.incode.sdk:model-liveness-detection:[VERSION]`
- `com.incode.sdk:model-face-recognition:[VERSION]`

See [Installation](./flutter-installation) for the full Android dependency setup.

### Fallback to server authentication

When using `FaceAuthMode.local`, you can fall back to a one-time server authentication if the user is not found locally on the device. Fallback works only in 1:1 Face Login mode. Set `faceAuthModeFallback` to `true`.

```dart
FaceLogin faceLogin = FaceLogin(
  customerUUID: "yourCustomerUUID",
  faceAuthMode: FaceAuthMode.local,
  faceAuthModeFallback: true,
);
```

### Local mode thresholds

When using `FaceAuthMode.local`, adjust the spoof and recognition thresholds by setting `spoofThreshold` and `recognitionThreshold` on the `FaceLogin` object. Both parameters accept values between `0.0` and `1.0`.

- `spoofThreshold`: Defaults to `0.5`.
- `recognitionThreshold`: Defaults to `0.6`.

### Face mask check

By default, Face Login does **not** detect face masks. To enable face mask detection, set `faceMaskCheck` to `true`.

```dart
FaceLogin faceLogin = FaceLogin(
  customerUUID: "yourCustomerUUID",
  faceMaskCheck: true,
);
```

### Lenses check

By default, Face Login detects lenses (glasses). To turn off lens detection, set `lensesCheck` to `false`.

```dart
FaceLogin faceLogin = FaceLogin(
  customerUUID: "yourCustomerUUID",
  lensesCheck: false,
);
```

### Authentication logging

By default, each authentication attempt is logged and device statistics are tracked. To turn off logging for faster authentications, set `logAuthenticationEnabled` to `false`.

```dart
FaceLogin faceLogin = FaceLogin(
  customerUUID: "yourCustomerUUID",
  logAuthenticationEnabled: false,
);
```

When logging is enabled, the following data is collected for each authentication attempt:

- Transaction ID (a random UUID for the attempt)
- Customer ID
- Face image
- Frame size (image width and height)
- Face detection data (face size and position, landmark coordinates for eyes and mouth)
- Device type
- Device name
- OS version
- Authentication type (1:1 or 1:N)
- Authentication method (`SERVER` or `LOCAL`)
- Brightness
- Blurriness
- Recognition confidence
- Liveness confidence
- `clientRecognitionThreshold` (sent only in `LOCAL` mode)
- `clientLivenessThreshold` (sent only in `LOCAL` mode)

### End-to-End Encryption (E2EE)

By default, Face Login does not use E2EE. To enable it, set `e2eeEncryptionEnabled` to `true`.

```dart
FaceLogin faceLogin = FaceLogin(
  customerUUID: "yourCustomerUUID",
  e2eeEncryptionEnabled: true,
);
```

Note that the parameter name on `FaceLogin` is `e2eeEncryptionEnabled` (two Es), which differs from the session-level parameter `e2eEncryptionEnabled` (one E) on `OnboardingSessionConfiguration`. See [End-to-End Encryption (E2EE)](./flutter-e2ee) for full E2EE setup.

E2EE for Face Login is supported on Android only.

## Manage locally stored identities

When using 1:N Face Login with `FaceAuthMode.local`, you must add user identities to the device's local database. This section describes the methods for adding, removing, retrieving, and replacing locally stored identities.

To use these methods, you must use the SDK `-l` variant. See [SDK variants](./flutter-installation#sdk-variants) on the Installation page.

### Add a face

Use `addFace` to add a single identity to the local database. Provide a `FaceInfo` object containing the face template, customer UUID, and template ID.

```dart
FaceInfo faceInfo = FaceInfo(
  faceTemplate: template,
  customerUUID: uuid,
  templateId: templateId,
);

IncodeOnboardingSdk.addFace(
  faceInfo: faceInfo,
  onSuccess: (bool result) {
    print(result);
  },
  onError: (String error) {
    print(error);
  },
);
```

#### FaceInfo fields

- `faceTemplate`: String. Biometric representation of a user's face.
- `customerUUID`: String. Unique customer identifier in Incode's database.
- `templateId`: String. Unique identifier of the biometric face representation in Incode's database.

The `faceTemplate` and `templateId` values are generated during a user's onboarding process and can be retrieved through a backend API. Contact your Incode representative for details on how to obtain them.

### Remove a face

Use `removeFace` to remove a single identity from the local database by `customerUUID`.

```dart
IncodeOnboardingSdk.removeFace(
  customerUUID: "your_customer_uuid",
  onSuccess: (bool result) {
    print(result);
  },
  onError: (String error) {
    print(error);
  },
);
```

### Get all faces

Use `getFaces` to retrieve all currently stored identities.

```dart
IncodeOnboardingSdk.getFaces(
  onSuccess: (List<FaceInfo> faceInfos) {
    print("faceInfos: $faceInfos");
  },
  onError: (String error) {
    print(error);
  },
);
```

### Set multiple faces

Use `setFaces` to replace the entire local database with a list of `FaceInfo` objects.

<Callout icon="❗" theme="error">
  ### Warning

  `setFaces` wipes out all currently stored identities before adding the new ones. To add identities without clearing the database, use `addFace` individually.
</Callout>

```dart
final faceInfos = <FaceInfo>[
  FaceInfo("your_face_template", "your_customer_uuid", "your_template"),
  FaceInfo("your_face_template2", "your_customer_uuid2", "your_template2"),
];

IncodeOnboardingSdk.setFaces(
  faces: faceInfos,
  onSuccess: (bool result) {
    print("result: $result");
  },
  onError: (String error) {
    print(error);
  },
);
```

### Clear the face database

To clear the local database, call `setFaces` with an empty list.

```dart
IncodeOnboardingSdk.setFaces(
  faces: List.empty(),
  onSuccess: (bool result) {
    print("result: $result");
  },
  onError: (String error) {
    print(error);
  },
);
```

### Locally stored identities and deleteLocalUserData

Locally stored identities added via `addFace` or `setFaces` are not affected by calls to [`deleteLocalUserData`](./flutter-api-reference#deletelocaluserdata). That method only removes session-scoped data. To remove locally stored identities, use `removeFace` or `setFaces`.
