Skip to content

Facephi IAD Service

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

What is IAD Service?

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

Breaking change notice (2.0.0) Version 2.0.0 breaks public REST API compatibility with all previous 1.x.x releases. Integrations upgrading from 1.x.x must update endpoint paths, 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 is rejected when capture is missing
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 health and performance
  • Integrate seamlessly with your authentication workflows

Quick Start

Requirements

Component Requirement
OS Linux x86_64 (Ubuntu 24.04 recommended)
License Valid Facephi license file

Deploy with Docker

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-core-pro-fphi/facephi-iad-service:2.1.0

Verify it works

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

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

Typical responses:

{
  "message": "Healthy"
}
{
  "message": "2.1.0 Copyright © 2026 FacePhi Biometria. All rights reserved."
}

API Endpoints

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

Core Operations

Endpoint Method Purpose
/api/v1/iad/liveness/evaluate POST Evaluate encrypted capture liveness with a Facephi public contract
/api/v1/iad/extract POST Extract image from validated capture

Management

Endpoint Method Purpose
/api/v1/iad/version GET Service version and license status
/api/v1/iad/health GET Health check for monitoring
/api/v1/iad/config GET/POST Retrieve or update configuration

Experimental Replay Attack Mitigation

The service can enforce a freshness window on 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 freshness window is exceeded, the service returns HTTP 400 with message equal to Replay attack detected

Example deployment:

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-core-pro-fphi/facephi-iad-service:2.1.0

This feature is configured only at startup through environment variables. It is not part of config.json and is not 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
  • Override the same values through FACEPHI_IAD_REST_AUTH_* environment variables
  • GET /api/v1/iad/config omits all JWT auth keys
  • POST /api/v1/iad/config rejects all JWT auth keys; use startup configuration instead

Example config.json fragment:

{
  "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"
}

Example environment variables:

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

Detailed Capture Information (longDetails)

POST /api/v1/iad/liveness/evaluate accepts an optional multipart text field longDetails. It must be sent in the same multipart/form-data body as the required capture part.

  • Accepted values are true and false (case-insensitive, trimmed).
  • When longDetails is absent, empty, or false, the endpoint returns the standard public liveness payload.
  • Any other value is rejected with HTTP 400.

A successful response includes top-level additionalInfo only when all of the following are true:

  1. longDetails=true is sent with the capture.
  2. engine_bi_records_enabled resolves to true.
  3. engine_url points to an IAD Server that exposes both /check_capture_liveness and /bi_records.
  4. The BI record is found before the configured timeout budget expires.

Operational notes:

  • The service generates the correlation-id header internally; clients do not send it.
  • BI lookup uses the current UTC date window when querying /bi_records; keep the service host and the IAD Server clock synchronized.

Activation paths for the embedded-engine Docker flow:

  1. Set logger_long_detail=true in the service config.json.
  2. Set FACEPHI_IAD_LOGGER_LONG_DETAIL=true in the service environment.
  3. Set IAD_SERVER_BI_LOGS_ENABLED=true before starting the service; optionally set IAD_SERVER_BI_LOGS_PATH if you do not want the default /app/logs.

Why those options work:

  • When the service launches the embedded engine in Docker, enabling logger_long_detail makes src/App.cpp inject IAD_SERVER_BI_LOGS_ENABLED=true and a default BI logs path into the child engine process unless they were already defined.
  • Direct IAD_SERVER_BI_LOGS_* exports also work because the child engine inherits the parent environment.
  • If the service is pointing to an external engine instead of spawning one, configure the equivalent BI logging capability directly on that engine deployment.

Set the keys below in /app/config/config.json or update them through POST /api/v1/iad/config; FACEPHI_IAD_ENGINE_BI_RECORDS_* environment variables override the service configuration.

Example config.json fragment:

{
  "engine_url": "http://iad-server.internal:8080",
  "engine_bi_records_enabled": true,
  "engine_bi_records_max_retries": 3,
  "engine_bi_records_retry_delay_ms": 50,
  "engine_bi_records_timeout_ms": 300,
  "engine_bi_records_redact_request_data": true
}

Example runtime update:

curl -X POST http://localhost:6982/api/v1/iad/config \
  -H "Content-Type: application/json" \
  -d '{"config_json_string":"{\"engine_url\":\"http://iad-server.internal:8080\",\"engine_bi_records_enabled\":true,\"engine_bi_records_timeout_ms\":500,\"engine_bi_records_redact_request_data\":true}"}'

Example embedded-engine activation through the service-level flag:

export FACEPHI_IAD_LOGGER_LONG_DETAIL=true

Alternative direct activation through inherited internal engine variables:

export IAD_SERVER_BI_LOGS_ENABLED=true
export IAD_SERVER_BI_LOGS_PATH=/app/logs

Example request:

curl -X POST http://localhost:6982/api/v1/iad/liveness/evaluate \
  -F "capture=@capture.bin;type=application/octet-stream" \
  -F "longDetails=true"

Public Error Contract

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

Liveness Result

Successful POST /api/v1/iad/liveness/evaluate responses expose only the public fields below:

Field Meaning
diagnostic High-level result: Live or NoLive
reason Public reason value returned by the service
probability Public capture probability
score Public confidence score
faceProbability Optional public face-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 map the response to a documented public rejection reason.
UntrustedEnvironment The capture was rejected because the runtime environment is not considered trusted.
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 as the device 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 corrupted or tampered with.
UntrustedContent The capture was rejected because an injection attack was detected.
UntrustedContentLowConfidence The capture was rejected because the service detected signs of an injection attack with lower confidence; it should still be treated as a rejection.

When multiple rejection causes are present, the service returns the first documented public rejection value in the service response order.

Normalized Validation Errors

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

Scenario Public message
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 close to border NoneBecauseFaceTooCloseToBorder
Eyes closed NoneBecauseEyesClosed
Image or payload cannot be processed NoneBecauseImageDataError
License problem reported by the service runtime NoneBecauseLicenseError
Replay freshness window exceeded Replay attack detected
Unclassified liveness failure ErrorProcessing

For endpoint POST /api/v1/iad/extract, parse and decrypt payload 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 examples below intentionally use the 2.x public wire contract introduced in 2.0.0: the capture multipart field and the public response schema.

Liveness Evaluate

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

Response:

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

Extract Image

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

Response:

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

Get Configuration

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

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

Update Configuration

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

curl -X POST \
  -H "Content-Type: application/json" \
  -d '{"config_json_string":"{\"port\":6982,\"number_of_threads\":1,\"engine_url\":\"http://localhost:8080\",\"engine_bi_records_enabled\":true,\"engine_bi_records_timeout_ms\":500}"}' \
  http://localhost:6982/api/v1/iad/config

Response:

{
  "message": "Configuration updated successfully"
}

Configuration

Create /app/config/config.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",
  "engine_bi_records_enabled": true,
  "engine_bi_records_max_retries": 3,
  "engine_bi_records_retry_delay_ms": 50,
  "engine_bi_records_timeout_ms": 300,
  "engine_bi_records_redact_request_data": false
}

Key Parameters

Parameter Default Description
port 6982 Service listening port
number_of_threads 1 Worker threads for request handling
connection_timeout 60 Rest::Manager connection timeout
keep_alive_request_number 0 Maximum keep-alive requests
client_max_body_size 100 Maximum request body size in MB
logger_level "info" Logging level (trace/debug/info/warn/error)
auth_enabled false Require JWT authentication for protected endpoints
auth_jwt_secret "" HS256 shared secret used to validate JWTs
auth_accept_authorization_header true Accept Authorization: Bearer <jwt>
auth_accept_api_key_header true Accept JWTs in the configured API key header
auth_api_key_header_name "x-api-key" Header name used when API key token extraction 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 Verify capture-analysis SSL certificates
engine_verbose false Enable verbose capture-analysis proxy logs
engine_pool_size 4 Connection pool size
engine_url "http://localhost:8080" Base URL of the capture-analysis runtime
engine_bi_records_enabled true Enable additionalInfo retrieval for longDetails=true
engine_bi_records_max_retries 3 Retries while waiting for the BI record
engine_bi_records_retry_delay_ms 50 Delay between BI record retries in ms
engine_bi_records_timeout_ms 300 Total BI retrieval latency budget in ms
engine_bi_records_redact_request_data false Strip output.request_data from additionalInfo

Architecture Overview

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/>• Config 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

Documentation

Support

For licensing inquiries or technical support, contact your Facephi representative.