@ivt-argos/liveness-mobile
v0.1.1
Published
SDK de liveness facial para React Native (VisionCamera + MLKit)
Maintainers
Readme
@ivt-argos/liveness-mobile
SDK de liveness facial para React Native.
Motor de retos compartido con @ivt-argos/liveness-web via @ivt-argos/liveness-core.
Instalación
npm install @ivt-argos/liveness-mobile
# Dependencias nativas (peerDependencies)
npm install react-native-vision-camera @react-native-ml-kit/face-detection react-native-reanimated
# iOS
cd ios && pod installAndroid — AndroidManifest.xml
<uses-permission android:name="android.permission.CAMERA" />iOS — Info.plist
<key>NSCameraUsageDescription</key>
<string>Necesitamos la cámara para verificar tu identidad.</string>Uso
import { useState, useEffect } from 'react'
import { LivenessMobileSDK, LivenessCameraView } from '@ivt-argos/liveness-mobile'
function PantallaVerificacion({ userId, authToken }) {
const [sdk] = useState(() => new LivenessMobileSDK({
backendUrl: 'https://tu-api.com',
userId,
authToken,
onStateChange: (estado) => console.log('Estado:', estado),
}))
useEffect(() => {
sdk.iniciar()
.then(r => console.log('Autenticado:', r.autenticado))
.catch(e => console.error('Error:', e.code, e.message))
}, [sdk])
return <LivenessCameraView sdk={sdk} style={{ flex: 1 }} />
}API
LivenessMobileSDK
| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
| backendUrl | string | ✅ | URL base del backend (sin slash final) |
| userId | string | ✅ | ID del usuario a verificar |
| authToken | string | ⚠️ | JWT del usuario para obtener el session token |
| onStateChange | Function | No | Callback con el estado actual del flujo |
| onNoFace | Function | No | Callback cuando no se detecta rostro |
| config.maxReintentos | number | No | Reintentos ante error de red (default: 2) |
const sdk = new LivenessMobileSDK({ ... })
await sdk.iniciar() // → { autenticado: boolean, confianza_similitud: number }LivenessCameraView
| Prop | Tipo | Descripción |
|---|---|---|
| sdk | LivenessMobileSDK | Instancia del SDK (requerido) |
| style | StyleProp<ViewStyle> | Estilo del contenedor (ej. { flex: 1 }) |
| theme | object | Personalización visual (ver sección de personalización) |
Estados del flujo (LIVENESS_STATE)
import { LIVENESS_STATE } from '@ivt-argos/liveness-mobile'
// INICIANDO → Conectando con backend, abriendo cámara
// RETO_PARPADEO → Esperando parpadeo natural
// RETO_GIRO_IZQ → Esperando giro de cabeza hacia la izquierda
// RETO_GIRO_DER → Esperando giro de cabeza hacia la derecha
// RETO_CENTRAR → Volver al frente y mantener posición
// VERIFICANDO → Anti-spoof en curso (textura + profundidad + micro-movimiento)
// APROBADO → Liveness pasado, enviando al backend
// RECHAZADO → Falló algún reto o se detectó suplantación
// ERROR → Error técnico (cámara, red, etc.)El SDK elige aleatoriamente el orden de los retos y la dirección del giro en cada sesión. Hay 4 combinaciones posibles (orden A/B × izquierda/derecha), lo que dificulta los ataques de reproducción con video pre-grabado.
Personalización visual
<LivenessCameraView
sdk={sdk}
style={{ flex: 1 }}
theme={{
mensajes: {
RETO_PARPADEO: { texto: 'Blink naturally' },
RETO_GIRO_IZQ: { texto: 'Turn left', icono: '⬅️' },
RETO_GIRO_DER: { texto: 'Turn right', icono: '➡️' },
APROBADO: { texto: 'Processing...', icono: '⏳', color: '#8B5CF6' },
},
colorFondo: '#1a1a2e',
colorPanel: '#16213e',
textoSub: 'Good lighting required',
ocultarEstadoFinal: true,
}}
/>Manejo de errores
import { SDKError } from '@ivt-argos/liveness-mobile'
try {
await sdk.iniciar()
} catch (err) {
if (err instanceof SDKError) {
switch (err.code) {
case 'CAMERA_ERROR': // Permiso denegado o sin cámara
case 'LIVENESS_TIMEOUT': // No completó todos los retos en el tiempo límite total
case 'CHALLENGE_TIMEOUT': // Un reto individual no se completó en sus 5 segundos
case 'SPOOF_DETECTED': // Foto, pantalla o video detectado
case 'TOKEN_FETCH_FAILED': // No se pudo obtener token del backend
case 'NETWORK_ERROR': // Sin conexión al servidor
case 'BACKEND_ERROR': // El backend rechazó (4xx / 5xx)
}
}
}Arquitectura interna
LivenessCameraView (ui.rn.jsx)
│
├── useLivenessCamera (mlkit-adapter.js)
│ ├── VisionCamera → cámara nativa iOS/Android
│ ├── MLKit → detección facial offline (3–8ms/frame)
│ └── calcularVarianzaWorklet → anti-spoof sin Canvas
│
└── LivenessMobileSDK
├── ChallengeEngine (@ivt-argos/liveness-core)
│ ← EAR, giro direccional, centrado, anti-spoof — idéntico al web
└── construirPayloadFirmado + fetch → mismo backend que webDiferencias con @ivt-argos/liveness-web
| | liveness-web | liveness-mobile |
|---|---|---|
| Cámara | getUserMedia | VisionCamera nativo |
| Detección facial | MediaPipe CDN (WASM) | MLKit offline |
| Frame loop | requestAnimationFrame | frameProcessor (worklet) |
| Varianza textura | Canvas 2D getImageData | ArrayBuffer directo |
| UI | DOM + CSS | RN View + StyleSheet |
| Retos y algoritmos | @ivt-argos/liveness-core | @ivt-argos/liveness-core |
| Seguridad y backend | @ivt-argos/liveness-core | @ivt-argos/liveness-core |
