> 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/sdks/backend-sdk/iad.md).

# IAD Service

**API REST de detección de ataques de inyección (Injection Attack Detection)** — Protege tus sistemas biométricos frente a ataques de suplantación (spoofing).

## ¿Qué es IAD Service?

IAD Service es un microservicio de API REST que detecta ataques de inyección en capturas biométricas. Verifica que los datos biométricos provienen de fuentes reales, y no de repeticiones (replays) ni de entradas sintéticas.

> **Aviso de cambio incompatible (2.0.0)** La versión 2.0.0 rompe la compatibilidad de la API REST pública con todas las versiones 1.x.x anteriores. Las integraciones que actualicen desde 1.x.x deben actualizar las rutas de los endpoints, los nombres de los campos de las solicitudes multipart y el análisis de las respuestas correctas.

| Contrato 1.x.x                                                                                      | Contrato 2.0.0                                                                                                                               |
| --------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `POST /api/v1/iad/check-capture`                                                                    | `POST /api/v1/iad/liveness/evaluate`                                                                                                         |
| `POST /api/v1/iad/extract-image`                                                                    | `POST /api/v1/iad/extract`                                                                                                                   |
| campo multipart `file`                                                                              | campo multipart obligatorio `capture`; `file` se rechaza cuando falta `capture`                                                              |
| Payloads de éxito privados heredados (`capture_liveness`, `capture_type`, `rejection`, `mime_type`) | Payloads públicos de Facephi (`diagnostic`, `reason`, `probability`, `score`, `faceProbability`, `sdkDuration`, `queueDuration`, `mimeType`) |

**Úsalo para:**

* Extraer imágenes válidas de capturas autenticadas
* Monitorizar el estado y el rendimiento del sistema
* Integrarlo sin fricciones con tus flujos de autenticación

## Inicio rápido

### Requisitos

| Componente | Requisito                                  |
| ---------- | ------------------------------------------ |
| SO         | Linux x86\_64 (se recomienda Ubuntu 24.04) |
| Licencia   | Archivo de licencia válido de Facephi      |

### Despliegue con Docker

```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
```

### Comprobar que funciona

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

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

Respuestas típicas:

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

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

## Endpoints de la API

> **Nota de compatibilidad** Las rutas documentadas en esta página son válidas únicamente para la versión 2.0.0 y posteriores.

### Operaciones principales

| Endpoint                        | Método | Propósito                                                                    |
| ------------------------------- | ------ | ---------------------------------------------------------------------------- |
| `/api/v1/iad/liveness/evaluate` | POST   | Evalúa el liveness de una captura cifrada con el contrato público de Facephi |
| `/api/v1/iad/extract`           | POST   | Extrae la imagen de una captura validada                                     |

### Gestión

| Endpoint                         | Método   | Propósito                                                                             |
| -------------------------------- | -------- | ------------------------------------------------------------------------------------- |
| `/api/v1/iad/version`            | GET      | Versión del servicio y estado de la licencia                                          |
| `/api/v1/iad/health`             | GET      | Comprobación activa de estado (incluye snapshot `initialized` y `engine.lastHealth*`) |
| `/api/v1/iad/metrics`            | GET      | Snapshot JSON de métricas operativas y de calidad                                     |
| `/api/v1/iad/metrics/prometheus` | GET      | Snapshot equivalente en formato Prometheus                                            |
| `/api/v1/iad/config`             | GET/POST | Obtener o actualizar la configuración                                                 |

`/health` y `/metrics` tienen objetivos distintos:

* `/health` ejecuta la comprobación activa del engine y actualiza el snapshot de salud.
* `/metrics` expone contadores y snapshots en memoria, sin ejecutar comprobaciones activas caras en cada scrape.

## Mitigación experimental de ataques de repetición (replay)

El servicio puede aplicar una ventana de vigencia (freshness window) a los payloads de captura entrantes. Esta protección experimental está deshabilitada por defecto.

* Actívala con `FACEPHI_IAD_REPLAY_ATTACK_CHECKER_ENABLED=true`
* Ajusta la ventana de vigencia con `FACEPHI_IAD_REPLAY_ATTACK_TOLERANCE_TIME=<seconds>`
* Ventana de vigencia por defecto: `300` segundos
* Se aplica a los endpoints de procesamiento de capturas como `POST /api/v1/iad/liveness/evaluate` y `POST /api/v1/iad/extract`
* Cuando se supera la ventana de vigencia, el servicio devuelve HTTP `400` con `message` igual a `Replay attack detected`

Ejemplo de despliegue:

```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
```

Esta funcionalidad solo se configura al inicio mediante variables de entorno. No forma parte de `config.json` ni se expone a través de `GET|POST /api/v1/iad/config`.

## Autenticación JWT

La autenticación JWT es opcional y está deshabilitada por defecto.

* Configúrala al inicio mediante `config.json` con `auth_enabled`, `auth_jwt_secret`, `auth_accept_authorization_header`, `auth_accept_api_key_header` y `auth_api_key_header_name`
* Sobrescribe esos mismos valores mediante variables de entorno `FACEPHI_IAD_REST_AUTH_*`
* `GET /api/v1/iad/config` omite todas las claves de autenticación JWT
* `POST /api/v1/iad/config` rechaza todas las claves de autenticación JWT; usa en su lugar la configuración de inicio

Ejemplo de fragmento de `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"
}
```

Ejemplo de variables de entorno:

```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
```

## Contrato público de errores

En las respuestas HTTP públicas `400`, el servicio devuelve mensajes públicos documentados en el cuerpo de respuesta estándar.

### Resultado de Liveness

Las respuestas correctas de `POST /api/v1/iad/liveness/evaluate` exponen únicamente los siguientes campos públicos:

| Campo             | Significado                                                              |
| ----------------- | ------------------------------------------------------------------------ |
| `diagnostic`      | Resultado de alto nivel: `Live` o `NoLive`                               |
| `reason`          | Valor de motivo público devuelto por el servicio                         |
| `probability`     | Probabilidad pública de la captura                                       |
| `score`           | Puntuación de confianza pública                                          |
| `faceProbability` | Probabilidad pública opcional de liveness facial, cuando está disponible |
| `sdkDuration`     | Duración del análisis de la captura en milisegundos                      |
| `queueDuration`   | Duración en cola reportada por RestManager en milisegundos               |

Los valores posibles para `reason` son:

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

| `reason`                        | Significado                                                                                                                                           |
| ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| `None`                          | La captura fue aceptada como `Live` y no aplica ningún motivo de rechazo.                                                                             |
| `Unknown`                       | El servicio no pudo asignar la respuesta a un motivo de rechazo público documentado.                                                                  |
| `UntrustedEnvironment`          | La captura fue rechazada porque el entorno de ejecución no se considera de confianza.                                                                 |
| `SuspiciousActivity`            | La captura fue rechazada porque el dispositivo mostró patrones de actividad asociados a un ataque.                                                    |
| `UntrustedDevice`               | La captura fue rechazada porque no se pudo confiar en que el dispositivo fuera el que dice ser.                                                       |
| `SdkIntegrityViolation`         | La captura fue rechazada porque el SDK de captura o sus librerías parecen haber sido alterados.                                                       |
| `UntrustedCorruptedPayload`     | La captura fue rechazada porque el payload parece estar corrupto o manipulado.                                                                        |
| `UntrustedContent`              | La captura fue rechazada porque se detectó un ataque de inyección.                                                                                    |
| `UntrustedContentLowConfidence` | La captura fue rechazada porque el servicio detectó indicios de un ataque de inyección con menor confianza; debe tratarse igualmente como un rechazo. |

Cuando existen varias causas de rechazo, el servicio devuelve el primer valor de rechazo público documentado según el orden de respuesta del servicio.

### Errores de validación normalizados

Para el endpoint `POST /api/v1/iad/liveness/evaluate`, los fallos de validación de captura se devuelven como HTTP `400` con valores de `message` documentados, tales como:

| Escenario                                                  | `message` público                 |
| ---------------------------------------------------------- | --------------------------------- |
| Cara demasiado cerca                                       | `NoneBecauseFaceTooClose`         |
| Cara no encontrada                                         | `NoneBecauseFaceNotFound`         |
| Cara recortada                                             | `NoneBecauseFaceCropped`          |
| Cara ocluida                                               | `NoneBecauseFaceOccluded`         |
| Demasiadas caras                                           | `NoneBecauseTooManyFaces`         |
| Ángulo de la cara demasiado grande                         | `NoneBecauseAngleTooLarge`        |
| Cara demasiado pequeña                                     | `NoneBecauseFaceTooSmall`         |
| Cara demasiado cerca del borde                             | `NoneBecauseFaceTooCloseToBorder` |
| Ojos cerrados                                              | `NoneBecauseEyesClosed`           |
| No se puede procesar la imagen o el payload                | `NoneBecauseImageDataError`       |
| Problema de licencia reportado por el runtime del servicio | `NoneBecauseLicenseError`         |
| Ventana de vigencia de repetición superada                 | `Replay attack detected`          |
| Fallo de liveness sin clasificar                           | `ErrorProcessing`                 |

Para el endpoint `POST /api/v1/iad/extract`, los fallos de análisis y desencriptado del payload se devuelven como `NoneBecauseImageDataError`; las capturas expiradas rechazadas por la protección contra repeticiones devuelven `Replay attack detected`; los fallos de extracción sin clasificar se devuelven como `ErrorFacialImage`.

## Ejemplo de uso

> **Nota de actualización** Los siguientes ejemplos usan intencionadamente el contrato público 2.x introducido en la versión 2.0.0: el campo multipart `capture` y el esquema de respuesta pública.

### Evaluar Liveness

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

**Respuesta:**

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

### Extraer imagen

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

**Respuesta:**

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

### Obtener configuración

Devuelve la vista pública de la configuración en tiempo de ejecución. Las claves de autenticación JWT se omiten intencionadamente.

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

### Actualizar configuración

`POST /api/v1/iad/config` espera un objeto JSON con el campo `config_json_string`, que contiene la configuración completa serializada como una cadena JSON. Las claves de autenticación JWT son rechazadas por este endpoint y deben establecerse únicamente al inicio.

```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
```

**Respuesta:**

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

## Configuración

Crea `/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"
}
```

### Parámetros clave

| Parámetro                          | Por defecto             | Descripción                                                                           |
| ---------------------------------- | ----------------------- | ------------------------------------------------------------------------------------- |
| `port`                             | 6982                    | Puerto de escucha del servicio                                                        |
| `number_of_threads`                | 1                       | Hilos de trabajo para el procesamiento de solicitudes                                 |
| `connection_timeout`               | 60                      | Timeout de conexión de Rest::Manager                                                  |
| `keep_alive_request_number`        | 0                       | Número máximo de solicitudes keep-alive                                               |
| `client_max_body_size`             | 100                     | Tamaño máximo del cuerpo de la solicitud en MB                                        |
| `logger_level`                     | "info"                  | Nivel de log (trace/debug/info/warn/error)                                            |
| `auth_enabled`                     | false                   | Requiere autenticación JWT para los endpoints protegidos                              |
| `auth_jwt_secret`                  | ""                      | Secreto compartido HS256 usado para validar los JWT                                   |
| `auth_accept_authorization_header` | true                    | Acepta `Authorization: Bearer <jwt>`                                                  |
| `auth_accept_api_key_header`       | true                    | Acepta JWT en la cabecera de API key configurada                                      |
| `auth_api_key_header_name`         | "x-api-key"             | Nombre de la cabecera usada cuando la extracción de token por API key está habilitada |
| `engine_connection_timeout`        | 10000                   | Timeout de conexión (ms)                                                              |
| `engine_request_timeout`           | 60000                   | Timeout de solicitud (ms)                                                             |
| `engine_max_retries`               | 3                       | Intentos de reintento del engine                                                      |
| `engine_retry_delay`               | 1000                    | Retardo entre reintentos del engine en ms                                             |
| `engine_verify_ssl`                | false                   | Verifica los certificados SSL del análisis de capturas                                |
| `engine_verbose`                   | false                   | Habilita los logs detallados del proxy de análisis de capturas                        |
| `engine_pool_size`                 | 4                       | Tamaño del pool de conexiones                                                         |
| `engine_url`                       | `http://localhost:8080` | URL base del runtime de análisis de capturas                                          |

## Descripción general de la arquitectura

```mermaid
flowchart TD
    Client["Cliente<br/>Aplicación"]

      Client -->|HTTP/REST| IADService

      subgraph IADService["Facephi IAD Service"]
        Components["• Licencia<br/>• Endpoints<br/>• Validación de capturas<br/>• Mitigación de ataques de repetición<br/>• Pool de conexiones<br/>• Gestión de configuración"]
      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
```

## Soporte

Para consultas de licencia o soporte técnico, contacta con tu representante de Facephi.
