Enterprise Authentication

Repeated biometric authentication with enrollment templates for enterprise workforce management.

Enterprise Only

Enterprise Authentication is available for organizations with an active Enterprise plan. Contact Owl Eyes Team to enable authentication features for your organization.

Key Features

Multi-Capture Enrollment

Collect 3-5 face images for robust template creation with real-time quality feedback.

Fast Authentication

Single-capture face recognition with sub-2-second response times for seamless access.

Multi-Modal Biometrics

Optional voice authentication for enhanced security with face + voice fusion.

JavaScript SDK (Web)

Installation

npm install @owl-eyes/web-sdk

// Or via CDN
<script src="https://sdk.owl-eyes.com/v2/owl-eyes.js"></script>

OwlEyes.enroll() Method

Initiates the multi-capture enrollment flow for face and voice biometrics.

import OwlEyes from '@owl-eyes/web-sdk';

const owl = new OwlEyes({
  clientId: 'YOUR_CLIENT_ID',
  environment: 'production',
});

// POST /v1/enrollments
const enrollmentResult = await owl.enroll({
  organizationId: 'org_abc123',
  employeeId: 'emp_john_doe',
  options: {
    requireVoice: true,           // Enable voice enrollment
    minFaceCaptures: 3,           // Minimum photos required
    maxFaceCaptures: 5,           // Maximum photos allowed
    minVoiceSamples: 3,           // Voice samples if required
    maxVoiceSamples: 5,
    showQualityFeedback: true,    // Real-time quality guidance
    allowRetry: true,             // Allow retry per capture
  },
  metadata: {
    department: 'Engineering',
    location: 'NYC Office',
    accessLevel: 'high',
  },
  
  // Callbacks
  onCaptureStart: (type) => {
    console.log(`Starting ${type} capture...`);  // 'face' or 'voice'
  },
  onCaptureProgress: (progress) => {
    // { type: 'face', current: 2, total: 5, quality: 87 }
    updateProgressUI(progress);
  },
  onQualityFeedback: (feedback) => {
    // { passed: false, issues: ['too_dark', 'blurry'], guidance: '...' }
    showQualityGuidance(feedback);
  },
  onComplete: (result) => {
    if (result.success) {
      console.log('Enrollment complete!', result.data);
    }
  },
  onError: (error) => {
    console.error('Enrollment failed:', error.code, error.message);
  },
});

OwlEyes.authenticate() Method

Performs fast, single-capture authentication against enrolled templates.

// POST /v1/authenticate
const authResult = await owl.authenticate({
  organizationId: 'org_abc123',
  employeeId: 'emp_john_doe',  // Employee claiming identity
  options: {
    requireVoice: false,       // Face-only for speed
    livenessMode: 'passive',   // 'passive' | 'active' | 'both'
    captureTimeout: 30,        // Seconds
  },
  deviceContext: {
    // Optional: helps detect fraud patterns
    deviceId: getDeviceFingerprint(),
    platform: 'web',
    userAgent: navigator.userAgent,
  },
  
  onCapturing: () => {
    showLoadingState();
  },
  onSuccess: (result) => {
    if (result.decision === 'authenticated') {
      // Access granted
      console.log('Welcome!', result.employee);
      redirectToApp();
    } else if (result.decision === 'challenge_required') {
      // Need to complete liveness challenge
      handleLivenessChallenge(result.challenges);
    } else if (result.decision === 'manual_review') {
      showPendingReviewMessage();
    }
  },
  onDenied: (result) => {
    console.log('Access denied. Flags:', result.flags);
    showAccessDeniedUI(result);
  },
  onError: (error) => {
    handleAuthError(error);
  },
});

TypeScript Definitions

Enrollment Response

interface EnrollmentResponse {
  success: boolean;
  data: {
    id: string;                    // Template ID
    organizationId: string;
    employeeId: string;
    status: 'active' | 'pending_voice' | 'pending_quality_review' | 'failed';
    source: 'from_verification' | 'standalone' | 'bulk_import';
    faceQualityScore: number;      // 0-100
    voiceQualityScore: number | null;
    captureQuality: CaptureQualityFeedback[];
    voiceSampleQuality?: VoiceSampleQualityFeedback[];
    enrolledAt: string;            // ISO timestamp
    flags: EnrollmentFlag[];
    metadata?: Record<string, string>;
  };
  error?: {
    code: EnrollmentErrorCode;
    message: string;
    details?: Record<string, unknown>;
  };
}

interface CaptureQualityFeedback {
  score: number;                   // 0-100
  passed: boolean;
  issues: FaceQualityIssue[];
  guidance?: string;
}

type FaceQualityIssue = 
  | 'too_dark' 
  | 'too_bright' 
  | 'blurry' 
  | 'face_too_small' 
  | 'face_too_large'
  | 'face_not_centered' 
  | 'multiple_faces' 
  | 'no_face_detected'
  | 'poor_lighting' 
  | 'motion_blur' 
  | 'occluded';

type EnrollmentFlag = 
  | 'duplicate_face_in_org' 
  | 'duplicate_face_cross_org'
  | 'duplicate_voice' 
  | 'low_quality_enrollment' 
  | 'watchlist_match';

Authentication Response

interface AuthenticationResponse {
  success: boolean;
  data: {
    sessionId: string;
    decision: 'authenticated' | 'denied' | 'challenge_required' | 'manual_review';
    confidenceBand: 'high' | 'medium' | 'low' | 'no_match';
    scores: {
      faceMatch: number;           // 0-100
      voiceMatch: number | null;   // 0-100 or null if not used
      liveness: number;            // 0-100
      deepfakeScore: number;       // 0-100 (100 = definitely real)
      combined: number;            // 0-100 weighted score
    };
    flags: AuthenticationFlag[];
    challenges?: LivenessChallenge[];  // If challenge_required
    employee?: {
      employeeId: string;
      metadata?: Record<string, string>;
      lastAuthenticatedAt?: string;
    };
    authenticatedAt: string;
    processingTimeMs: number;
  };
  error?: {
    code: AuthenticationErrorCode;
    message: string;
  };
}

type AuthenticationFlag = 
  | 'liveness_failed'
  | 'deepfake_suspected'
  | 'face_mismatch'
  | 'voice_mismatch'
  | 'watchlist_hit'
  | 'velocity_anomaly'
  | 'device_anomaly'
  | 'location_anomaly'
  | 'impossible_travel';

Error Codes

Enrollment Error Codes

CodeDescription
ENROLLMENT_ALREADY_EXISTSEmployee already has an active enrollment
QUALITY_TOO_LOWCaptured images don't meet quality threshold
DUPLICATE_FACE_DETECTEDFace matches an existing enrollment
ENROLLMENT_QUOTA_EXCEEDEDOrganization has reached enrollment limit
INSUFFICIENT_SAMPLESNot enough quality samples collected

Authentication Error Codes

CodeDescription
EMPLOYEE_NOT_ENROLLEDNo enrollment found for this employee
ENROLLMENT_SUSPENDEDEmployee enrollment is temporarily suspended
LIVENESS_FAILEDLiveness detection did not pass
DEEPFAKE_DETECTEDPotential deepfake or spoofing attempt
ACCOUNT_LOCKEDToo many failed attempts, account locked
RATE_LIMITEDToo many requests, slow down
CAPTURE_QUALITY_TOO_LOWPoor image quality, retry with better conditions

Browser Compatibility

BrowserFace CaptureVoice CaptureNotes
Chrome 80+✓ Full Support✓ Full SupportRecommended
Firefox 75+✓ Full Support✓ Full Support
Safari 14+✓ Full Support✓ Full SupportRequires HTTPS
Edge 80+✓ Full Support✓ Full SupportChromium-based

Bundle size: ~45KB gzipped (within 50KB target). Requires HTTPS for camera/microphone access.

Handling Permissions

The SDK automatically handles camera and microphone permission requests. You can check permission status beforehand:

// Check permissions before starting
const permissions = await owl.checkPermissions();

if (!permissions.camera) {
  // Show guidance to enable camera
  showCameraPermissionGuide();
}

if (options.requireVoice && !permissions.microphone) {
  // Show guidance to enable microphone
  showMicrophonePermissionGuide();
}

// Permissions object
interface PermissionStatus {
  camera: 'granted' | 'denied' | 'prompt';
  microphone: 'granted' | 'denied' | 'prompt';
}
Security Reminder

Never expose your API secret key in client-side code. All enrollment and authentication requests should be initiated from your backend, which then provides session tokens to the frontend SDK.