npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

kora-identity-react-native-sdk

v0.3.0

Published

Kora liveness check react native sdk

Readme

Kora Liveness Check React Native SDK

A modern React Native SDK for face liveness detection powered by a service-based architecture. Provides seamless integration with backend APIs and supports both passive and active liveness detection.

Features

  • 🎯 Auto-Initialization: SDK initializes automatically when needed
  • 🤖 Auto-Determined Liveness Type: Let the backend choose optimal liveness type automatically
  • 🔄 Provider Agnostic: Currently supports YouVerify with easy extensibility
  • 🛠️ TypeScript Support: Full type safety and IntelliSense
  • 📱 React Native Optimized: Designed specifically for mobile apps
  • 🎨 Customizable: Configurable branding, user info, and settings
  • 🔒 Secure: Sandbox and production mode support
  • 📊 Production Error Tracking: Automatic error reporting to Kora's monitoring system
  • 🏗️ Modular Architecture: Clean separation of concerns with provider pattern
  • 🚀 Future-Ready: Easily extensible for multiple liveness providers

Installation

npm install kora-identity-react-native-sdk
# or
yarn add kora-identity-react-native-sdk

Dependencies

Make sure you have react-native-webview installed:

npm install react-native-webview
# or
yarn add react-native-webview

For iOS, run pod install:

cd ios && pod install

Camera Permissions Setup

The SDK requires camera access for liveness verification. Follow these steps:

Android: Add to android/app/src/main/AndroidManifest.xml:

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />

iOS: Add to ios/YourApp/Info.plist:

<key>NSCameraUsageDescription</key>
<string>This app needs camera access for liveness verification</string>
<key>NSMicrophoneUsageDescription</key>
<string>This app may need microphone access for liveness verification</string>

For detailed permission setup, see CAMERA_PERMISSIONS.md.

Security Features

Built-in Security: The SDK automatically includes a secure FileProvider configuration that overrides the default react-native-webview configuration, protecting against potential file access vulnerabilities.

The SDK includes secure file provider paths that restrict access to only app-specific directories, preventing unauthorized access to external storage or system files.

Quick Start

Auto-Determined Liveness Type (Recommended)

The SDK can automatically determine whether to use active or passive liveness based on your backend configuration, eliminating the need to specify the type manually:

import React, { useState } from 'react';
import { View, Button, Alert } from 'react-native';
import { koraLivenessService } from 'kora-identity-react-native-sdk';

const App = () => {
  const [livenessComponent, setLivenessComponent] =
    useState<React.ReactElement | null>(null);

  const startAutoLivenessCheck = async () => {
    try {
      // No type specified - backend will determine optimal liveness type
      const component = await koraLivenessService.checkLiveness({
        // SDK Configuration (auto-initialization)
        publicKey: 'your-kora-public-key',

        // User Configuration
        user: {
          firstName: 'John',
          lastName: 'Doe',
          email: '[email protected]',
        },
        branding: {
          color: '#2376F3',
        },
        onSuccess: (result) => {
          Alert.alert('Success', 'Liveness check passed!');
          console.log('Success result:', result);
          setLivenessComponent(null);
        },
        onFailure: (result) => {
          Alert.alert('Failed', `Liveness check failed: ${result.error}`);
          setLivenessComponent(null);
        },
        onClose: () => {
          setLivenessComponent(null);
        },
      });

      setLivenessComponent(component);
    } catch (error) {
      Alert.alert('Error', `Failed to start: ${error}`);
    }
  };

  if (livenessComponent) {
    return <View style={{ flex: 1 }}>{livenessComponent}</View>;
  }

  return (
    <View style={{ flex: 1, justifyContent: 'center', padding: 20 }}>
      <Button
        title="Start Auto-Determined Liveness"
        onPress={startAutoLivenessCheck}
      />
    </View>
  );
};

Explicit Liveness Type (Backward Compatible)

You can still specify the liveness type explicitly if needed:

const App = () => {
  const [livenessComponent, setLivenessComponent] =
    useState<React.ReactElement | null>(null);

  const startLivenessCheck = async () => {
    try {
      // Explicit type specification
      const component = await koraLivenessService.checkLiveness({
        type: 'passive', // Explicitly specify the type
        publicKey: 'your-kora-public-key',
        user: {
          firstName: 'John',
          lastName: 'Doe',
          email: '[email protected]',
        },
        branding: {
          color: '#2376F3',
        },
        onSuccess: (result) => {
          Alert.alert('Success', 'Liveness check passed!');
          setLivenessComponent(null);
        },
        onFailure: (result) => {
          Alert.alert('Failed', `Liveness check failed: ${result.error}`);
          setLivenessComponent(null);
        },
        onClose: () => {
          setLivenessComponent(null);
        },
      });

      setLivenessComponent(component);
    } catch (error) {
      Alert.alert('Error', `Failed to start: ${error}`);
    }
  };

  if (livenessComponent) {
    return <View style={{ flex: 1 }}>{livenessComponent}</View>;
  }

  return (
    <View style={{ flex: 1, justifyContent: 'center', padding: 20 }}>
      <Button title="Start Passive Liveness" onPress={startLivenessCheck} />
    </View>
  );
};

Component Wrapper (Alternative)

For easier integration, you can use the LivenessCheck component wrapper:

import React, { useState } from 'react';
import { View, Button } from 'react-native';
import { LivenessCheck } from 'kora-identity-react-native-sdk';

const App = () => {
  const [showLiveness, setShowLiveness] = useState(false);

  if (showLiveness) {
    return (
      <View style={{ flex: 1 }}>
        <LivenessCheck
          publicKey="your-kora-public-key"
          // type prop is optional - omit for auto-determination
          config={{
            user: {
              firstName: 'John',
              lastName: 'Doe',
              email: '[email protected]',
            },
            branding: {
              color: '#2376F3',
            },
          }}
          onSuccess={(result) => {
            console.log('Success:', result);
            setShowLiveness(false);
          }}
          onFailure={(result) => {
            console.log('Failed:', result);
            setShowLiveness(false);
          }}
          onClose={() => setShowLiveness(false)}
        />
      </View>
    );
  }

  return (
    <View style={{ flex: 1, justifyContent: 'center', padding: 20 }}>
      <Button
        title="Start Auto Liveness Check"
        onPress={() => setShowLiveness(true)}
      />
    </View>
  );
};

Manual Initialization (Alternative)

You can still manually initialize the service if preferred:

const App = () => {
  const [livenessComponent, setLivenessComponent] =
    useState<React.ReactElement | null>(null);

  const startLivenessCheck = async () => {
    try {
      // Manual initialization (optional if using auto-initialization above)
      await koraLivenessService.initialize({
        publicKey: 'your-kora-public-key',
      });

      // Start liveness check with auto-determined type
      const component = await koraLivenessService.checkLiveness({
        user: { firstName: 'John', lastName: 'Doe' },
        branding: { color: '#2376F3' },
        onSuccess: (result) => {
          /* handle success */
        },
        onFailure: (result) => {
          /* handle failure */
        },
        onClose: () => {
          /* handle close */
        },
      });

      setLivenessComponent(component);
    } catch (error) {
      Alert.alert('Error', `Failed to start: ${error}`);
    }
  };

  // ... rest of component
};

Configuration Options

User Configuration

user: {
  firstName: string;    // Required
  lastName?: string;    // Optional
  email?: string;       // Optional
}

Branding Configuration

branding: {
  color?: string;       // Primary color (hex code) - defaults to Kora blue (#2376F3) if not provided
  logo?: string;        // Custom logo URL or base64 string - optional
}

Advanced Configuration

{
  // Environment is automatically determined from public key:
  // pk_test_* = sandbox, pk_live_* = live environment
  apiBaseUrl?: string;            // Override API endpoint (for internal testing only)
  allowAudio?: boolean;           // Allow audio prompts (default: false)
  presentation?: 'modal' | 'page'; // Presentation mode
  tasks?: Array<{                 // Custom tasks
    id: string;
    difficulty?: 'easy' | 'medium' | 'hard';
    timeout?: number;
    maxBlinks?: number;
    maxNods?: number;
  }>;
}

Note: The SDK automatically connects to Kora's production API. Backend URL configuration has been removed to ensure consistent service connectivity.

Architecture

Modular Design

The SDK is built with a modular, provider-agnostic architecture that ensures maintainability and extensibility:

// Core Architecture Layers
import { Logger } from 'kora-liveness-check-rn-sdk/utils';
import { BaseLivenessProvider } from 'kora-liveness-check-rn-sdk/providers';
import { ProviderFactory } from 'kora-liveness-check-rn-sdk/providers';

Error Tracking & Logging

The SDK includes production-ready error tracking that automatically reports issues to Kora's monitoring system:

// Automatic error tracking (no setup required)
const component = await koraLivenessService.checkLiveness({
  type: 'passive',
  // ... other config
});

// Manual logging (for custom implementations)
import { Logger } from 'kora-liveness-check-rn-sdk/utils';

const logger = Logger.getInstance();
logger.logError('Custom error message', error, { userId: '123' });

Provider System

The SDK supports multiple liveness providers through a factory pattern:

import {
  ProviderFactory,
  LivenessProvider,
} from 'kora-liveness-check-rn-sdk/providers';

// Get the current provider
const provider: LivenessProvider = ProviderFactory.getProvider('youverify');

// Extend for custom providers
class CustomProvider extends BaseLivenessProvider {
  async initialize(config: any): Promise<void> {
    // Custom initialization logic
  }

  async checkLiveness(type: string, config: any): Promise<any> {
    // Custom liveness check implementation
  }
}

API Reference

Service API

koraLivenessService.checkLiveness(config)

Start a liveness check and return a React component with auto-initialization.

const component = await koraLivenessService.checkLiveness({
  // Type Configuration (optional)
  type?: 'passive' | 'active',    // Optional: Omit for auto-determination

  // SDK Configuration (auto-initialization)
  publicKey: string;               // Required: Your Kora public key

  // User Configuration
  user?: {
    firstName: string;
    lastName?: string;
    email?: string;
  };

  // Branding Configuration
  branding?: {
    color?: string;
    logo?: string;
    name?: string;
  };

  // Task Configuration (optional)
  allowAudio?: boolean;
  tasks?: Array<{
    id: string;
    difficulty?: 'easy' | 'medium' | 'hard';
  }>;

  // Callbacks
  onSuccess?: (result) => void;
  onFailure?: (result) => void;
  onClose?: () => void;
});

Auto-Determination vs Explicit Type

// Auto-determined type (recommended)
const autoComponent = await koraLivenessService.checkLiveness({
  publicKey: 'your-key',
  user: { firstName: 'John' },
  // No type or tasks - backend determines optimal settings
});

// Explicit type (backward compatible)
const explicitComponent = await koraLivenessService.checkLiveness({
  type: 'active',
  publicKey: 'your-key',
  user: { firstName: 'John' },
  tasks: [{ id: 'complete_the_circle' }], // Custom tasks
});

koraLivenessService.initialize(options) (Optional)

Manually initialize the Kora Liveness service.

await koraLivenessService.initialize({
  publicKey: string;           // Required: Your Kora public key
});

Component API

<LivenessCheck />

React component for liveness detection.

Props:

  • publicKey: Your Kora public key (required)
  • type?: Liveness type - 'passive' | 'active' (optional - omit for auto-determination)
  • config?: Configuration object (optional)
  • onSuccess: Success callback function (required)
  • onFailure: Failure callback function (required)
  • onClose: Close callback function (required)
  • onStart?: Optional start callback
  • style?: Optional style object
  • loadingComponent?: Optional loading component
  • errorComponent?: Optional error component

useLivenessCheck(props)

Hook for managing liveness check state.

const {
  result,
  isLoading,
  error,
  startLivenessCheck,
  handleSuccess,
  handleFailure,
  handleClose,
  LivenessComponent,
} = useLivenessCheck({
  publicKey: 'your-key',
  type?: 'passive', // Optional - omit for auto-determination
  config: { /* ... */ }
});

Auto-Determined Liveness Type

Overview

The SDK now supports automatic liveness type determination, where the backend chooses the optimal liveness verification method based on your business configuration and requirements. This eliminates the need for developers to decide between 'active' and 'passive' liveness checks.

How It Works

  1. Omit the type parameter when calling checkLiveness()
  2. Backend determines optimal type based on your account configuration
  3. SDK extracts the type from the backend response (liveness_check_type)
  4. Component renders with the backend-determined settings

Benefits

  • 🤖 Smart Defaults: Backend chooses the best liveness type for your use case
  • 🔧 Simplified Integration: No need to decide between active/passive
  • 🎯 Business Logic: Type determination based on your account settings
  • 🔄 Backward Compatible: Explicit type specification still works
  • Optimized Flow: Conditional API payloads for better performance

Usage Examples

Auto-Determined Type (Recommended)

// Backend determines the optimal liveness type
const component = await koraLivenessService.checkLiveness({
  publicKey: 'your-kora-public-key',
  user: {
    firstName: 'John',
    lastName: 'Doe',
  },
  onSuccess: (result) => {
    console.log('Liveness type was:', result.metadata?.type);
    console.log('Success:', result);
  },
  onFailure: (result) => console.log('Failed:', result),
});

Explicit Type (Backward Compatible)

// Explicitly specify the liveness type
const component = await koraLivenessService.checkLiveness({
  type: 'active', // Force active liveness
  publicKey: 'your-kora-public-key',
  user: {
    firstName: 'John',
    lastName: 'Doe',
  },
  tasks: [{ id: 'complete_the_circle' }], // Custom tasks for active
  onSuccess: (result) => console.log('Success:', result),
  onFailure: (result) => console.log('Failed:', result),
});

Comparison

| Feature | Auto-Determined | Explicit Type | | -------------------- | ------------------------------ | ------------------------- | | Type Parameter | Omitted | 'active' or 'passive' | | Tasks Parameter | Omitted (backend decides) | Optional (custom tasks) | | API Payload | Minimal (no type/tasks) | Full (includes type) | | Backend Response | Contains liveness_check_type | Mirrors provided type | | Use Case | Most applications | Custom requirements |

Configuration Details

When using auto-determined type:

  • No type field is sent to the backend
  • No tasks field is sent to the backend
  • Backend responds with liveness_check_type
  • SDK configures component with backend-determined settings

When using explicit type:

  • Type field is sent to the backend
  • Tasks field is sent if provided
  • Backend mirrors the provided type
  • SDK uses the explicitly provided settings

Liveness Types

Passive Liveness

  • No user interaction required
  • User just needs to look at the camera
  • Faster and easier for users
  • Good for most use cases

Active Liveness

  • Requires user interaction (head movement, blinking, etc.)
  • More secure against spoofing attacks
  • Takes longer to complete
  • Better for high-security applications

Available Tasks

The SDK supports various liveness verification tasks that can be configured based on your requirements:

Passive Liveness Tasks

  • passive - Default passive liveness detection
    • No user interaction required
    • User simply looks at the camera
    • Automatically set when using passive liveness type

Active Liveness Tasks

Active liveness tasks require user interaction and can be customized with additional parameters:

complete_the_circle (Recommended)

{
  id: 'complete_the_circle', // or 'complete-the-circle'
  difficulty: 'medium',
  timeout: 30000
}
  • User traces a circle on screen
  • Most commonly used active task
  • Default task for active liveness detection

blink

{
  id: 'blink',
  difficulty: 'easy',
  maxBlinks: 3
}
  • User performs blinking actions
  • Configurable with maxBlinks parameter

motions

{
  id: 'motions',
  difficulty: 'medium', 
  maxBlinks: 2,
  maxNods: 2
}
  • Combined head movements and blinking
  • Supports both maxBlinks and maxNods parameters
  • More comprehensive interaction task

yes_or_no

{
  id: 'yes_or_no', // or 'yes-or-no'
  questions: [
    {
      question: 'Are you ready to proceed?',
      answer: true,
      errorMessage: 'Please nod your head to the right for yes'
    }
  ]
}
  • User responds to yes/no questions by nodding
  • Supports custom questions with configurable error messages

Task Configuration Parameters

Each task supports these optional configuration parameters:

interface LivenessTask {
  id: string;                              // Task identifier (required)
  difficulty?: 'easy' | 'medium' | 'hard'; // Task difficulty level
  timeout?: number;                        // Task timeout in milliseconds
  maxBlinks?: number;                      // Max blinks (for blink/motions tasks)
  maxNods?: number;                        // Max nods (for motions/yes_or_no tasks)
  questions?: Array<{                      // For yes_or_no tasks
    question: string;
    answer: boolean;
    errorMessage?: string;
  }>;
}

Usage Examples

Single Task

const component = await koraLivenessService.checkLiveness({
  type: 'active',
  publicKey: 'your-key',
  tasks: [{ 
    id: 'complete_the_circle',
    difficulty: 'medium' 
  }],
  // ... other config
});

Multiple Tasks

const component = await koraLivenessService.checkLiveness({
  type: 'active', 
  publicKey: 'your-key',
  tasks: [
    { id: 'blink', maxBlinks: 3 },
    { id: 'motions', maxNods: 2, maxBlinks: 2 }
  ],
  // ... other config
});

Auto-Determined Tasks (Recommended)

// Let backend choose optimal tasks automatically
const component = await koraLivenessService.checkLiveness({
  publicKey: 'your-key',
  user: { firstName: 'John' },
  // No type or tasks specified - backend determines everything
});

Task Recommendations

  • For simplicity: Use auto-determination (omit type and tasks)
  • For basic security: Use complete_the_circle
  • For enhanced security: Combine multiple tasks like ['blink', 'motions']
  • For custom flows: Use yes_or_no with custom questions
  • For user experience: Stick to 1-2 tasks maximum to avoid fatigue

Error Handling

The SDK provides comprehensive error handling:

// Service API
try {
  const component = await koraLivenessService.checkLiveness({
    type: 'passive',
    publicKey: 'your-key',
    onFailure: (result) => {
      console.log('Error code:', result.error);
      console.log('Error data:', result.data);
      console.log('Metadata:', result.metadata);
    },
  });
} catch (error) {
  console.log('Initialization error:', error.message);
}

// Component API
<LivenessCheck
  publicKey="your-key"
  onFailure={(result) => {
    if (result.error) {
      // Handle specific error
    }
  }}
  errorComponent={<YourCustomErrorComponent />}
/>;

Session Management

// Get current session information
const session = koraLivenessService.getCurrentSession();
console.log('Session ID:', session.sessionId);
console.log('Session Token:', session.sessionToken);

// Clear session data
koraLivenessService.clearCache();

// Reset service completely
koraLivenessService.reset();

Debug Information

// Get debug information
const debug = koraLivenessService.getDebugInfo();
console.log('Debug info:', debug);

Types

LivenessResult

interface LivenessResult {
  success: boolean;
  data?: any;
  error?: string;
  metadata?: Record<string, any>;
}

KoraLivenessConfig

interface KoraLivenessConfig {
  type?: 'active' | 'passive'; // Optional: Omit for auto-determination
  publicKey?: string; // Environment auto-detected: pk_test_* = sandbox, pk_live_* = live
  apiBaseUrl?: string; // Override API endpoint (for internal testing)
  user?: LivenessUser;
  branding?: LivenessBranding;
  presentation?: 'modal' | 'page';
  allowAudio?: boolean;
  tasks?: LivenessTask[]; // Optional: Only for explicit type
  onSuccess?: (result: LivenessResult) => void;
  onFailure?: (result: LivenessResult) => void;
  onClose?: () => void;
  onStart?: () => void;
}

KoraLivenessOptions (New Interface)

interface KoraLivenessOptions extends KoraLivenessConfig {
  type?: LivenessType; // 'active' | 'passive' | undefined
}

Migration Guide

From v1.x to v2.x (Auto-Determined Liveness)

Before (v1.x - Old Pattern)

// Step 1: Initialize
await koraLivenessService.initialize({
  publicKey: 'your-key',
});

// Step 2: Start liveness with explicit type
const component = await koraLivenessService.checkLiveness('passive', {
  user: { firstName: 'John' },
  onSuccess: (result) => {
    /* success */
  },
});

After (v2.x - New Pattern)

Option 1: Auto-Determined Type (Recommended)

// Single step: Auto-initialize and auto-determine type
const component = await koraLivenessService.checkLiveness({
  publicKey: 'your-key',
  user: { firstName: 'John' },
  onSuccess: (result) => {
    console.log('Backend chose type:', result.metadata?.type);
    /* success */
  },
});

Option 2: Explicit Type (Backward Compatible)

// Single step: Auto-initialize with explicit type
const component = await koraLivenessService.checkLiveness({
  type: 'passive', // Explicitly specify type
  publicKey: 'your-key',
  user: { firstName: 'John' },
  onSuccess: (result) => {
    /* success */
  },
});

Breaking Changes

  • New Method Signature: checkLiveness() now accepts a single config object instead of (type, config)
  • Type Parameter: Now optional - omit for auto-determination
  • Backward Compatibility: Old pattern still supported via explicit type property
  • Enhanced Response: Success callback includes determined type in metadata

Migration Steps

  1. Update method calls from checkLiveness(type, config) to checkLiveness(config)
  2. Add type to config if you want explicit type: { type: 'passive', ...config }
  3. Remove type from config if you want auto-determination
  4. Update TypeScript types if using custom interfaces

Troubleshooting

Common Issues

  1. WebView not loading: Ensure react-native-webview is properly installed and linked.

  2. Network errors: Check your API key and network connectivity.

  3. iOS build issues: Run cd ios && pod install after installation.

  4. Android build issues: Ensure your Android project supports WebView.

Getting Help

  • Check the example app in the repository for comprehensive configuration options
  • Review the API documentation
  • Contact Kora support for API key issues

Platform Support

  • iOS: 11.0+
  • Android: API 21+ (Android 5.0)
  • React Native: 0.60+

License

This SDK is proprietary software. See LICENSE for details.