> For the complete documentation index, see [llms.txt](https://docs.facephi.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.facephi.com/docs.facephi-en/sdks/backend-sdk/iad.md).

# IAD Service

**Injection Attack Detection REST API (Injection Attack Detection)** — Protect your biometric systems against spoofing attacks.

## What is IAD Service?

IAD Service is a REST API microservice that detects injection attacks in biometric captures. It verifies that biometric data comes from real sources, rather than replays or synthetic inputs.

> **Incompatible change notice (2.0.0)** Version 2.0.0 breaks public REST API compatibility with all previous 1.x.x versions. Integrations upgrading from 1.x.x must update endpoint routes, multipart request field names, and successful response parsing.

| 1.x.x contract                                                                                 | 2.0.0 contract                                                                                                                          |
| ---------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| `POST /api/v1/iad/check-capture`                                                               | `POST /api/v1/iad/liveness/evaluate`                                                                                                    |
| `POST /api/v1/iad/extract-image`                                                               | `POST /api/v1/iad/extract`                                                                                                              |
| multipart field `file`                                                                         | required multipart field `capture`; `file` rejected when missing `capture`                                                              |
| Legacy private success payloads (`capture_liveness`, `capture_type`, `rejection`, `mime_type`) | Facephi public payloads (`diagnostic`, `reason`, `probability`, `score`, `faceProbability`, `sdkDuration`, `queueDuration`, `mimeType`) |

**Use it to:**

* Extract valid images from authenticated captures
* Monitor system status and performance
* Integrate it seamlessly with your authentication flows

## Quick start

### Requirements

| Component | Requirement                                 |
| --------- | ------------------------------------------- |
| OS        | Linux x86\_64 (Ubuntu 24.04 is recommended) |
| License   | Valid Facephi License file                  |

### Docker deployment

```bash
docker run -d \
  -p 6982:6982 \
  -v /path/to/license:/app/license \
  -v /path/to/config:/app/config \
  --name iad-service \
  facephicorp.jfrog.io/docker-pro-fphi/facephi-iad-service:2.2.0
```

### Check that it works

```bash
# Check health
curl http://localhost:6982/api/v1/iad/health

# Check version
curl http://localhost:6982/api/v1/iad/version
```

Typical responses:

```json
{
  "message": "Healthy"
}
```

```json
{
  "message": "2.2.0 Copyright © 2026 FacePhi Biometria. All rights reserved."
}
```

## API endpoints

> **Compatibility note** The routes documented on this page are valid only for version 2.0.0 and later.

### Main operations

| Endpoint                        | Method | Purpose                                                                        |
| ------------------------------- | ------ | ------------------------------------------------------------------------------ |
| `/api/v1/iad/liveness/evaluate` | POST   | Evaluates the Liveness of an encrypted capture using Facephi's public contract |
| `/api/v1/iad/extract`           | POST   | Extracts the image from a validated capture                                    |

### Management

| Endpoint                         | Method   | Purpose                                                                        |
| -------------------------------- | -------- | ------------------------------------------------------------------------------ |
| `/api/v1/iad/version`            | GET      | Service version and license status                                             |
| `/api/v1/iad/health`             | GET      | Active health check (includes snapshot `initialized` and `engine.lastHealth*`) |
| `/api/v1/iad/metrics`            | GET      | JSON snapshot of operational and quality metrics                               |
| `/api/v1/iad/metrics/prometheus` | GET      | Equivalent snapshot in Prometheus format                                       |
| `/api/v1/iad/config`             | GET/POST | Get or update the configuration                                                |

`/health` and `/metrics` have different purposes:

* `/health` runs the engine's active check and updates the health snapshot.
* `/metrics` exposes in-memory counters and snapshots without running expensive active checks on every scrape.

## Experimental mitigation against replay attacks

The service can apply a freshness window to incoming capture payloads. This experimental protection is disabled by default.

* Enable it with `FACEPHI_IAD_REPLAY_ATTACK_CHECKER_ENABLED=true`
* Adjust the freshness window with `FACEPHI_IAD_REPLAY_ATTACK_TOLERANCE_TIME=<seconds>`
* Default freshness window: `300` seconds
* Applies to capture processing endpoints such as `POST /api/v1/iad/liveness/evaluate` and `POST /api/v1/iad/extract`
* When the validity window is exceeded, the service returns HTTP `400` with `message` equal to `Replay attack detected`

Deployment example:

```bash
docker run -d \
  -p 6982:6982 \
  -e FACEPHI_IAD_REPLAY_ATTACK_CHECKER_ENABLED=true \
  -e FACEPHI_IAD_REPLAY_ATTACK_TOLERANCE_TIME=60 \
  -v /path/to/license:/app/license \
  -v /path/to/config:/app/config \
  --name iad-service \
  facephicorp.jfrog.io/docker-pro-fphi/facephi-iad-service:2.2.0
```

This feature is configured only at startup through environment variables. It is not part of `config.json` or exposed through `GET|POST /api/v1/iad/config`.

## JWT authentication

JWT authentication is optional and disabled by default.

* Configure it at startup through `config.json` with `auth_enabled`, `auth_jwt_secret`, `auth_accept_authorization_header`, `auth_accept_api_key_header` and `auth_api_key_header_name`
* Overrides those same values through environment variables `FACEPHI_IAD_REST_AUTH_*`
* `GET /api/v1/iad/config` omits all JWT authentication keys
* `POST /api/v1/iad/config` rejects all JWT authentication keys; use the startup configuration instead

Example snippet of `config.json`:

```json
{
  "auth_enabled": true,
  "auth_jwt_secret": "replace-with-secret",
  "auth_accept_authorization_header": true,
  "auth_accept_api_key_header": true,
  "auth_api_key_header_name": "x-api-key"
}
```

Environment variables example:

```bash
export FACEPHI_IAD_REST_AUTH_ENABLED=true
export FACEPHI_IAD_REST_AUTH_JWT_SECRET=replace-with-secret
export FACEPHI_IAD_REST_AUTH_ACCEPT_AUTHORIZATION_HEADER=true
export FACEPHI_IAD_REST_AUTH_ACCEPT_API_KEY_HEADER=true
export FACEPHI_IAD_REST_AUTH_API_KEY_HEADER_NAME=x-api-key
```

## Public error contract

In public HTTP responses `400`, the service returns documented public messages in the standard response body.

### Liveness result

Successful responses from `POST /api/v1/iad/liveness/evaluate` expose only the following public fields:

| Field             | Meaning                                                     |
| ----------------- | ----------------------------------------------------------- |
| `diagnostic`      | High-level result: `Live` or `NoLive`                       |
| `reason`          | Public reason value returned by the service                 |
| `probability`     | Public probability of the capture                           |
| `score`           | Public confidence score                                     |
| `faceProbability` | Optional public facial Liveness probability, when available |
| `sdkDuration`     | Capture analysis duration in milliseconds                   |
| `queueDuration`   | Queue duration reported by RestManager in milliseconds      |

Possible values for `reason` are:

* `None`
* `Unknown`
* `UntrustedEnvironment`
* `SuspiciousActivity`
* `UntrustedDevice`
* `SdkIntegrityViolation`
* `UntrustedCorruptedPayload`
* `UntrustedContent`
* `UntrustedContentLowConfidence`

| `reason`                        | Meaning                                                                                                                                                  |
| ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `None`                          | The capture was accepted as `Live` and no rejection reason applies.                                                                                      |
| `Unknown`                       | The service could not assign the response to a documented public rejection reason.                                                                       |
| `UntrustedEnvironment`          | The capture was rejected because the runtime environment is not considered trustworthy.                                                                  |
| `SuspiciousActivity`            | The capture was rejected because the device showed activity patterns associated with an attack.                                                          |
| `UntrustedDevice`               | The capture was rejected because the device could not be trusted to be what it claims to be.                                                             |
| `SdkIntegrityViolation`         | The capture was rejected because the capture SDK or its libraries appear to have been altered.                                                           |
| `UntrustedCorruptedPayload`     | The capture was rejected because the payload appears to be corrupted or tampered with.                                                                   |
| `UntrustedContent`              | The capture was rejected because an injection attack was detected.                                                                                       |
| `UntrustedContentLowConfidence` | The capture was rejected because the service detected indications of an injection attack with lower confidence; it must still be treated as a rejection. |

When there are multiple rejection causes, the service returns the first documented public rejection value according to the service response order.

### Standardized validation errors

For the endpoint `POST /api/v1/iad/liveness/evaluate`, capture validation failures are returned as HTTP `400` with `message` documented values, such as:

| Scenario                                      | `message` public                  |
| --------------------------------------------- | --------------------------------- |
| Face too close                                | `NoneBecauseFaceTooClose`         |
| Face not found                                | `NoneBecauseFaceNotFound`         |
| Face cropped                                  | `NoneBecauseFaceCropped`          |
| Face occluded                                 | `NoneBecauseFaceOccluded`         |
| Too many faces                                | `NoneBecauseTooManyFaces`         |
| Face angle too large                          | `NoneBecauseAngleTooLarge`        |
| Face too small                                | `NoneBecauseFaceTooSmall`         |
| Face too close to the edge                    | `NoneBecauseFaceTooCloseToBorder` |
| Eyes closed                                   | `NoneBecauseEyesClosed`           |
| Unable to process the image or payload        | `NoneBecauseImageDataError`       |
| License issue reported by the service runtime | `NoneBecauseLicenseError`         |
| Replay validity window exceeded               | `Replay attack detected`          |
| Unclassified Liveness failure                 | `ErrorProcessing`                 |

For the endpoint `POST /api/v1/iad/extract`, payload analysis and decryption failures are returned as `NoneBecauseImageDataError`; expired captures rejected by replay protection return `Replay attack detected`; unclassified extraction failures are returned as `ErrorFacialImage`.

## Usage example

> **Upgrade note** The following examples intentionally use the public 2.x contract introduced in version 2.0.0: the multipart field `capture` and the public response schema.

### Evaluate Liveness

```bash
curl -X POST \
  -F "capture=@biometric_capture.bin" \
  http://localhost:6982/api/v1/iad/liveness/evaluate
```

**Response:**

```json
{
  "diagnostic": "Live",
  "reason": "None",
  "probability": 1,
  "score": 1,
  "sdkDuration": 12,
  "queueDuration": 3
}
```

### Extract image

```bash
curl -X POST \
  -F "capture=@biometric_capture.bin" \
  http://localhost:6982/api/v1/iad/extract
```

**Response:**

```json
{
  "image": "base64_encoded_image...",
  "mimeType": "image/jpeg"
}
```

### Get configuration

Returns the public view of the runtime configuration. JWT authentication keys are intentionally omitted.

```bash
curl http://localhost:6982/api/v1/iad/config
```

### Update configuration

`POST /api/v1/iad/config` expects a JSON object with the field `config_json_string`, which contains the complete configuration serialized as a JSON string. JWT authentication keys are rejected by this endpoint and must be set only at startup.

```bash
curl -X POST \
  -H "Content-Type: application/json" \
  -d '{"config_json_string":"{\"port\":6982,\"number_of_threads\":1,\"engine_url\":\"http://localhost:8080\",\"engine_pool_size\":8}"}' \
  http://localhost:6982/api/v1/iad/config
```

**Response:**

```json
{
  "message": "Configuration updated successfully"
}
```

## Configuration

Create `/app/config/config.json`:

```json
{
  "port": 6982,
  "number_of_threads": 1,
  "connection_timeout": 60,
  "keep_alive_request_number": 0,
  "client_max_body_size": 100,
  "logger_level": "info",
  "logger_path": "/app/logs",
  "logger_rotation": "daily",
  "logger_max_files": 7,
  "auth_enabled": false,
  "auth_jwt_secret": "",
  "auth_accept_authorization_header": true,
  "auth_accept_api_key_header": true,
  "auth_api_key_header_name": "x-api-key",
  "engine_connection_timeout": 10000,
  "engine_request_timeout": 60000,
  "engine_max_retries": 3,
  "engine_retry_delay": 1000,
  "engine_verify_ssl": false,
  "engine_verbose": false,
  "engine_pool_size": 4,
  "engine_url": "http://localhost:8080"
}
```

### Key parameters

| Parameter                          | Default                 | Description                                                  |
| ---------------------------------- | ----------------------- | ------------------------------------------------------------ |
| `port`                             | 6982                    | Service listening port                                       |
| `number_of_threads`                | 1                       | Worker threads for request processing                        |
| `connection_timeout`               | 60                      | Rest::Manager connection Timeout                             |
| `keep_alive_request_number`        | 0                       | Maximum number of keep-alive requests                        |
| `client_max_body_size`             | 100                     | Maximum request body size in MB                              |
| `logger_level`                     | "info"                  | Log level (trace/debug/info/warn/error)                      |
| `auth_enabled`                     | false                   | Requires JWT authentication for protected endpoints          |
| `auth_jwt_secret`                  | ""                      | HS256 shared secret used to validate JWTs                    |
| `auth_accept_authorization_header` | true                    | Accepts `Authorization: Bearer <jwt>`                        |
| `auth_accept_api_key_header`       | true                    | Accepts JWT in the configured API key header                 |
| `auth_api_key_header_name`         | "x-api-key"             | Header name used when token extraction by API key is enabled |
| `engine_connection_timeout`        | 10000                   | Connection timeout (ms)                                      |
| `engine_request_timeout`           | 60000                   | Request timeout (ms)                                         |
| `engine_max_retries`               | 3                       | Engine retry attempts                                        |
| `engine_retry_delay`               | 1000                    | Delay between engine retries in ms                           |
| `engine_verify_ssl`                | false                   | Verifies SSL certificates from capture analysis              |
| `engine_verbose`                   | false                   | Enables detailed logs for the capture analysis proxy         |
| `engine_pool_size`                 | 4                       | Connection pool size                                         |
| `engine_url`                       | `http://localhost:8080` | Base URL of the capture analysis runtime                     |

## Architecture overview

```mermaid
flowchart TD
    Client["Client<br/>Application"]

      Client -->|HTTP/REST| IADService

      subgraph IADService["Facephi IAD Service"]
        Components["• License<br/>• Endpoints<br/>• Capture validation<br/>• Replay attack mitigation<br/>• Connection pool<br/>• Configuration management"]
      end

      style Client fill:#4a9eff,stroke:#333,stroke-width:2px,color:#000
      style IADService fill:#111111,stroke:#333,stroke-width:2px,color:#000
      style Components fill:#60a5fa,stroke:#333,stroke-width:2px,color:#000
```

## Support

For License or Technical Support inquiries, contact your Facephi representative.
